macro_rules! proptest { (#![proptest_config($config:expr)] $( $(#[$meta:meta])* fn $test_name:ident($($parm:pat in $strategy:expr),+ $(,)?) $body:block )*) => { ... }; (#![proptest_config($config:expr)] $( $(#[$meta:meta])* fn $test_name:ident($($arg:tt)+) $body:block )*) => { ... }; ($( $(#[$meta:meta])* fn $test_name:ident($($parm:pat in $strategy:expr),+ $(,)?) $body:block )*) => { ... }; ($( $(#[$meta:meta])* fn $test_name:ident($($arg:tt)+) $body:block )*) => { ... }; (|($($parm:pat in $strategy:expr),+ $(,)?)| $body:expr) => { ... }; (move |($($parm:pat in $strategy:expr),+ $(,)?)| $body:expr) => { ... }; (|($($arg:tt)+)| $body:expr) => { ... }; (move |($($arg:tt)+)| $body:expr) => { ... }; ($config:expr, |($($parm:pat in $strategy:expr),+ $(,)?)| $body:expr) => { ... }; ($config:expr, move |($($parm:pat in $strategy:expr),+ $(,)?)| $body:expr) => { ... }; ($config:expr, |($($arg:tt)+)| $body:expr) => { ... }; ($config:expr, move |($($arg:tt)+)| $body:expr) => { ... }; }
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.
§Example
use proptest::prelude::*;
proptest! {
#[test]
fn test_addition(a in 0..10, b in 0..10) {
prop_assert!(a + b <= 18);
}
#[test]
fn test_string_concat(a in ".*", b in ".*") {
let cat = format!("{}{}", a, b);
prop_assert_eq!(a.len() + b.len(), cat.len());
}
}
You can also use the normal argument syntax pattern: type
as in:
use proptest::prelude::*;
proptest! {
#[test]
fn addition_is_commutative(a: u8, b: u8) {
prop_assert_eq!(a as u16 + b as u16, b as u16 + a as u16);
}
#[test]
fn test_string_concat(a in ".*", b: String) {
let cat = format!("{}{}", a, b);
prop_assert_eq!(a.len() + b.len(), cat.len());
}
}
As you can see, you can mix pattern: type
and pattern in expr
.
Due to limitations in macro_rules!
, pattern: type
does not work in
all circumstances. In such a case, use (pattern): type
instead.
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).
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. In this form, proptest!
is a function-like macro taking a
closure-esque argument. This makes 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.
To use a custom configuration, pass the Config
object as a first
argument.
§Example
use proptest::prelude::*;
#[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.
// Note the extra parentheses around the arguments 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
});
// You can pass a custom configuration as the first argument
proptest!(ProptestConfig::with_cases(1000), |(x: i32)| {
// Test more stuff
});
}