#[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