#[property_test]Expand description
A variant of #[gpui::test] that supports property-based testing.
A property test, much like a standard GPUI randomized test, allows testing claims of the form “for any possible X, Y should hold”. For example:
#[gpui::property_test]
fn test_arithmetic(x: i32, y: i32) {
assert!(x == y || x < y || x > y);
}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 - the harness also understands a notion of the “complexity” of a particular value. This allows it to find the “simplest possible value that causes the test to fail”.
- Ergonomics/clarity - the property-testing harness will automatically generate values, removing the need to fill the test body with generation logic.
- Failure persistence - if a failing seed is identified, it is stored in a file, which can be checked in, and future runs will check these cases before future 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.
Note: much of the following is copied from the proptest docs, specifically the
[#[proptest::property_test]] macro docs.
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, you can use #[strategy = ...] on the argument:
#[gpui::property_test]
fn int_test(#[strategy = 1..10] x: i32, #[strategy = "[a-zA-Z0-9]{20}"] s: String) {
assert!(s.len() > (x as usize));
}For more information on writing custom Strategy and Arbitrary
implementations, see [the proptest book][book], and the [Strategy] trait.
§Scheduler
Similar to #[gpui::test], this macro will choose random seeds for the test
scheduler. It uses .no_shrink() to tell proptest that all seeds are
roughly equivalent in terms of “complexity”. If $SEED is set, it will
affect ONLY the seed passed to the scheduler. 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