Macro proptest::proptest

source ·
macro_rules! proptest {
    (#![proptest_config($config:expr)]
     $(
        $(#[$meta:meta])*
        fn $test_name:ident($($parm:pat in $strategy:expr),+) $body:block
    )*) => { ... };
    ($(
        $(#[$meta:meta])*
        fn $test_name:ident($($parm:pat in $strategy:expr),+) $body:block
    )*) => { ... };
    (|($($parm:pat in $strategy:expr),+)| $body:block) => { ... };
    (move |($($parm:pat in $strategy:expr),+)| $body:block) => { ... };
}
Expand description

Easily define proptest tests.

Within proptest!, define one or more functions without return type normally, except instead of putting : type after each parameter, write in strategy, where strategy is an expression evaluating to some Strategy.

Each function will be wrapped in a function which sets up a TestRunner, and then invokes the function body with inputs generated according to the strategies. Note that the inputs are borrowed from the test runner, so if they are not Copy, you will need to use ref with each parameter name.

Example

#[macro_use] extern crate proptest;

proptest! {
  #[test]
  fn test_addition(a in 0..10, b in 0..10) {
    prop_assert!(a + b <= 18);
  }

  // Note the `ref a` and `ref b` --- `String` is not `Copy`,
  // so we can't take ownership implicitly.
  #[test]
  fn test_string_concat(ref a in ".*", ref b in ".*") {
    let cat = format!("{}{}", a, b);
    prop_assert_eq!(a.len() + b.len(), cat.len());
  }
}

To override the default configuration, you can start the proptest! block with #![proptest_config(expr)], where expr is an expression that evaluates to a proptest::test_runner::Config (or a reference to one).

#[macro_use] extern crate proptest;
use proptest::prelude::*;

proptest! {
  #![proptest_config(ProptestConfig {
    cases: 99, .. ProptestConfig::default()
  })]
  #[test]
  fn test_addition(a in 0..10, b in 0..10) {
    prop_assert!(a + b <= 18);
  }
}

Closure-Style Invocation

As of proptest 0.8.1, an alternative, “closure-style” invocation is supported. These make it possible to run multiple tests that require some expensive setup process. Note that the “fork” and “timeout” features are not supported in closure style. There is currently no way to specify a custom configuration for closure style.

Example

#[macro_use] extern crate proptest;

#[derive(Debug)]
struct BigStruct { /* Lots of fields ... */ }

fn very_expensive_function() -> BigStruct {
  // Lots of code...
  BigStruct { /* fields */ }
}

#[test]
fn my_test() {
  // We create just one `BigStruct`
  let big_struct = very_expensive_function();

  // But now can run multiple tests without needing to build it every time.
  // Braces around the test body are currently required.
  proptest!(|(x in 0u32..42u32, y in 1000u32..100000u32)| {
    // Test stuff
  });

  // `move` closures are also supported
  proptest!(move |(x in 0u32..42u32)| {
    // Test other stuff
  });
}