Repository navigation
Description
Problem
Rust has no built-in way to write one test for many inputs. Tests that check a list of inputs do it in one of two ways:
- They loop over an array inside one
#[test]. - They put several asserts in one function, often with comments that say why each input is there.
Both ways have the same problems:
- The test stops at the first input that fails. The inputs after it do not run, so one run does not show all the failures.
- The test reports one failure for the whole function. The output names the input only if the assert message prints it.
cargo testcannot run one input by itself.
Proposed solution
Adopt rstest as the tool for parameterized tests. Each #[case] is a separate test: it passes or fails by itself, its name shows in the output, and cargo test can filter by that name.
rstest is the most used parameterized-test crate for Rust. On crates.io it has about 2.4 times the recent downloads of test-case, the next most used crate, and about 3 times as many dependent crates. It has a release every few months, and it works with #[tokio::test] async fn.
Before:
#[test]
fn test_rejects_unsupported_schemes() {
for url in ["ftp://example.com/a", "file:///tmp/a", "ws://example.com/a"] {
assert!(validate_url(url).is_err());
}
}After:
#[rstest]
#[case::ftp("ftp://example.com/a")]
#[case::file("file:///tmp/a")]
#[case::websocket("ws://example.com/a")]
fn test_rejects_unsupported_schemes(#[case] url: &str) {
assert!(validate_url(url).is_err());
}A failure is then reported as test_rejects_unsupported_schemes::case_2_file.
When to use rstest
Use #[rstest] with #[case] when a test runs the same check on a list of inputs. Name each case (#[case::name(...)]), so the name says what the input is. A name can replace a comment that explained the input.
Keep a plain #[test] when:
- The test is a scenario with its own setup and asserts.
- The test loops over results from one shared setup. The loop is then part of the scenario, not a list of inputs.
Out of scope
- rstest fixtures (
#[fixture]) for shared setup. These can be a later issue. #[values]matrices and#[files]cases. Use these only when a test needs them.
Acceptance criteria
-
rstestis a dev-dependency of each crate that has parameterized tests. - Tests that loop over a list of inputs, or that put several inputs in one function, use
#[rstest]with one named case for each input. - No input is removed. The number of inputs checked is the same as before.
-
cargo test --workspacepasses, andcargo testcan run a single case by its name.
Activity
velocitysystems commentedon Nov 6, 2026
Closed by #75.