Using the Test Runner
Rather than manually shrinking, proptest’s
TestRunner provides this
functionality for us and additionally handles things like panics. The
method we’re interested in is run. We simply
give it the strategy and a function to test inputs and it takes care of the
rest.
use proptest::test_runner::{Config, FileFailurePersistence, TestError, TestRunner}; fn some_function(v: i32) { // Do a bunch of stuff, but crash if v > 500. // We return to normal `assert!` here since `TestRunner` catches // panics. assert!(v <= 500); } // We know the function is broken, so use a purpose-built main function to // find the breaking point. fn main() { let mut runner = TestRunner::new(Config { // Turn failure persistence off for demonstration failure_persistence: Some(Box::new(FileFailurePersistence::Off)), .. Config::default() }); let result = runner.run(&(0..10000i32), |v| { some_function(v); Ok(()) }); match result { Err(TestError::Fail(_, value)) => { println!("Found minimal failing case: {}", value); assert_eq!(501, value); }, result => panic!("Unexpected result: {:?}", result), } }
That’s a lot better! Still a bit boilerplatey; the proptest! macro will
help with that, but it does some other stuff we haven’t covered yet, so for
the moment we’ll keep using TestRunner directly.