Skip to main content

property_test

Attribute Macro property_test 

Source
#[property_test]
Expand description

A variant of #[gpui::test] that runs a test with many generated inputs.

A property test checks a claim for many generated inputs. For example, a function with x: i32 and y: i32 runs for generated pairs of integers; the test body should hold for every pair.

Standard GPUI randomized tests provide you with an instance of StdRng to generate random data in a controlled manner. Property-based tests have some advantages, however:

  • Shrinking reduces a failing input to a smaller case that still fails.
  • The harness generates values, so the test body contains only the property.
  • Failing cases are saved to a file and replayed before new cases.

Property tests work best when all inputs can be generated up-front and kept in a simple data structure. Sometimes, this isn’t possible - for example, if a test needs to make a random decision based on the current state of some structure. In this case, a standard GPUI randomized test may be more suitable.

§Customizing random values

This macro is based on the [#[proptest::property_test]] macro, but handles some of the same GPUI-specific arguments as #[gpui::test]. Specifically, &{mut,} TestAppContext and BackgroundExecutor work as normal. StdRng arguments are explicitly forbidden, since they break shrinking, and are a common footgun.

All other arguments are forwarded to the underlying proptest macro.

The code that proptest’s macro generates names the proptest crate directly, so a crate that uses this macro needs proptest, with its attr-macro feature, in its dev-dependencies.

The following terms come from proptest’s [#[proptest::property_test]] documentation.

Random values of type T are generated by a Strategy<Value = T> object. Some types have a canonical Strategy - these types also implement Arbitrary. Parameters to a #[gpui::property_test], by default, use a type’s Arbitrary implementation. If you’d like to provide a custom strategy, put #[strategy = ...] on the argument. For example, #[strategy = 1..10] x: i32 draws x from the range 1..10.

For more information on writing custom Strategy and Arbitrary implementations, see [the proptest book][book], and the [Strategy] trait.

§Scheduler

Each case receives a scheduler seed, which the macro supplies as a parameter that doesn’t shrink, because all seeds are equally simple. Without SEED, the case seeds come from a proptest generator fixed at 0, so runs are reproducible. If SEED is set, every case uses that value as its scheduler seed, and the proptest generator is seeded with it too. To control other values, use custom Strategys.

[#[proptest::property_test]]: https://docs.rs/proptest/latest/proptest/attr.property_test.html [book]: https://proptest-rs.github.io/proptest/intro.html [Strategy]: https://docs.rs/proptest/latest/proptest/strategy/trait.Strategy.html