
Flaky Tests in Rust and Seven Usual Causes to Check
Seven usual causes of tests that pass and fail at random in Rust, with a check and a fix for each: shared state, ports, time, HashMap order, threads, files and the environment.
Unit, doc and integration tests, property testing and mocks, enough to refactor without flinching.

Seven usual causes of tests that pass and fail at random in Rust, with a check and a fix for each: shared state, ports, time, HashMap order, threads, files and the environment.

Benchmarks fail by measuring nothing: the optimizer deletes the work, the input is unrealistic, the machine is noisy or the harness measures setup. Here are the traps and how to avoid each.

Assert that code panics with should_panic and a message, or with catch_unwind for finer control. Know the traps: unrelated panics passing, Result tests and panic=abort.

Miri interprets your tests and reports undefined behavior in unsafe code: out of bounds access, use after free, bad aliasing and uninitialized reads. Here is how to run and read it.

Test a CLI end to end with assert_cmd and predicates: run the real binary, check the exit status, stdout and stderr, feed stdin and use temporary files.

Microbenchmarks mislead when the optimizer deletes work, inputs are unrealistic or caches are warm. Learn the usual lies and how to write benchmarks you can trust.

cargo-nextest runs each test in its own process with better parallelism, clear output, retries and JUnit reports. See install, speed expectations, config and what it does not run.

Make code that uses random numbers testable: inject the generator, seed it, test properties instead of values, and keep production randomness unpredictable.

Make code that depends on the clock testable: pass the time in, define a Clock trait or closure, use a fake clock that you advance, and pause time in Tokio tests.

Insta stores the expected output of a test in a file and shows a diff when it changes. Learn the review workflow with cargo insta, inline snapshots, redactions and when snapshots go wrong.

Criterion gives statistics and plots on stable Rust; Divan gives a lighter attribute-based API with allocation counting. Compare setup, output, features and pitfalls.

Fuzz a Rust function with cargo-fuzz and libFuzzer: init, write a target, run, read crashes, minimize inputs, add a corpus and turn findings into regression tests.
We send one email when a new post is published. No spam.