Forking and Timeouts

By default, proptest tests are run in-process and are allowed to run for however long it takes them. This is resource-efficient and produces the nicest test output, and for many use cases is sufficient. However, problems like overflowing the stack, aborting the process, or getting stuck in an infinite loop will simply break the entire test process and prevent proptest from determining a minimal reproducible case.

As of version 0.7.1, proptest has optional “fork” and “timeout” features (both enabled by default), which make it possible to run your test cases in a subprocess and limit how long they may run. This is generally slower, may make using a debugger more difficult, and makes test output harder to interpret, but allows proptest to find and minimise test cases for these situations as well.

To use these features, simply set the fork and/or timeout fields on the Config. (Setting timeout implies fork.)

Here is a simple example of using both features:

use proptest::prelude::*;

// The worst possible way to calculate Fibonacci numbers
fn fib(n: u64) -> u64 {
    if n <= 1 {
        n
    } else {
        fib(n - 1) + fib(n - 2)
    }
}

proptest! {
    #![proptest_config(ProptestConfig {
        // Setting both fork and timeout is redundant since timeout implies
        // fork, but both are shown for clarity.
        fork: true,
        timeout: 1000,
        .. ProptestConfig::default()
    })]

    #[test]
    fn test_fib(n: u64) {
        // For large n, this will variously run for an extremely long time,
        // overflow the stack, or panic due to integer overflow.
        assert!(fib(n) >= n);
    }
}
# //NOREADME
# fn main() { } //NOREADME

The exact value of the test failure depends heavily on the performance of the host system, the rust version, and compiler flags, but on the system where it was originally tested, it found that the maximum value that fib() could handle was 39, despite having dozens of processes dump core due to stack overflow or time out along the way.

If you just want to run tests in subprocesses or with a timeout every now and then, you can do that by setting the PROPTEST_FORK or PROPTEST_TIMEOUT environment variables to alter the default configuration. For example, on Unix,

# Run all the proptest tests in subprocesses with no timeout.
# Individual tests can still opt out by setting `fork: false` in their
# own configuration.
PROPTEST_FORK=true cargo test
# Run all the proptest tests in subprocesses with a 1 second timeout.
# Tests can still opt out or use a different timeout by setting `timeout: 0`
# or another timeout in their own configuration.
PROPTEST_TIMEOUT=1000 cargo test