Skip to content

Latest commit

 

History

History
53 lines (40 loc) · 1.98 KB

README.md

File metadata and controls

53 lines (40 loc) · 1.98 KB

sample-test: utilities for sample testing

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))
    }
}

Prior Work

This library was heavily inspired by quickcheck and proptest.

Here's where it differs:

  • quickcheck works 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.
  • proptest uses 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-test is slightly more complicated than quickcheck, with the benefit of easier definition of sampling strategies.
  • sample-test is not as good at shrinking as proptest as it does not record the seed values that were used to generate a given output.