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.