Create tests that sample arbitrary data to produce counterexamples for a given proposition:
use sample_std::VecSampler;
use sample_test::{sample_test, TestResult};
#[sample_test]
fn age_range(#[sample(VecSampler { el: 1..25, length: 0..50 })] ages: Vec<u8>) -> TestResult {
if ages.iter().all(|a| *a < 5) {
TestResult::discard()
} else {
TestResult::from_bool(ages.iter().all(|a| *a < 25))
}
}This library was heavily inspired by quickcheck and proptest.
Here's where it differs:
quickcheckworks at the type level, and thus creating a new sampling strategy requires an entirely new type. This gets painfully verbose with complex types and many different sampling strategies.proptestuses macros to create strategies, and creates a tree of seed values to shrink data. This tree can get very large for recursive data, and macros can be a pain to work with.
This library attempts to split the difference. It allows user-defined Sample
strategies which are fed into tests. Shrinking, like with quickcheck,
operates directly on generated values. This avoids the need to create and
maintain the seed tree used by proptest, and allows this library to
scale up to larger generated data sizes.
Instead of macros, this library and any downstream users rely heavily on
Sample combinators. This is inspired by Iterator composition which
is very performant and concise, all without the need for any macros.
The tradeoffs are:
sample-testis slightly more complicated thanquickcheck, with the benefit of easier definition of sampling strategies.sample-testis not as good at shrinking asproptestas it does not record the seed values that were used to generate a given output.