cargo-nextest - Next-Generation Rust Test Runner Cheatsheet
cargo-nextest is a next-generation test runner for Rust. Its core architectural difference from cargo test is that it runs each test in its own process, which gives true isolation (one test cannot corrupt another’s global state), better parallelism, and the ability to report a test that crashes the process rather than losing the whole run. In practice it is typically 2–3x faster than cargo test on large suites, with much cleaner output, flaky-test detection, and partitioning for CI sharding.
Installation
| Method | Command |
|---|
| Prebuilt (fastest) | cargo install cargo-nextest --locked |
| Binary | download from the nextest releases |
| macOS (Homebrew) | brew install cargo-nextest |
| Verify | cargo nextest --version |
Basic Usage
| Command | Description |
|---|
cargo nextest run | Run all tests |
cargo nextest run -p mycrate | One package |
cargo nextest run test_name | Filter by substring |
cargo nextest list | List tests without running |
cargo nextest run --release | Release profile |
cargo nextest run --no-fail-fast | Keep going after failures |
Filtering (Filtersets)
nextest has an expression language for selecting tests.
| Expression | Selects |
|---|
-E 'test(auth)' | Tests whose name matches auth |
-E 'package(mycrate)' | All tests in a package |
-E 'kind(lib)' | Only lib (unit) tests |
-E 'binary(integration)' | A specific test binary |
-E 'test(a) + test(b)' | Union |
-E 'package(x) - test(slow)' | Difference |
# Run integration tests for one crate, excluding slow ones
cargo nextest run -E 'package(api) and kind(test) - test(slow)'
Flaky Test Detection
# Retry failures up to 3 times; tests that pass on retry are marked FLAKY
cargo nextest run --retries 3
| Config | Effect |
|---|
--retries N | Retry failed tests N times |
| Reported as FLAKY | Passed only after a retry |
| Per-test overrides | Set retries for specific tests in config |
This distinction matters: a flaky test is a different problem from a failing test, and nextest surfaces it explicitly instead of hiding it behind a rerun.
Configuration
# .config/nextest.toml
[profile.default]
retries = 0
fail-fast = false
slow-timeout = { period = "30s", terminate-after = 2 }
[profile.ci]
retries = 2
failure-output = "immediate-final"
status-level = "skip"
[[profile.default.overrides]]
filter = 'test(integration)'
threads-required = 2
| Setting | Purpose |
|---|
retries | Default retry count |
slow-timeout | Flag/kill tests exceeding a duration |
threads-required | Reserve capacity for heavy tests |
failure-output | When to print failure details |
| Profiles | cargo nextest run -P ci |
CI Sharding
# Split the suite across 4 CI machines
cargo nextest run --partition count:1/4 # on runner 1
cargo nextest run --partition count:2/4 # on runner 2
| Mode | Splits by |
|---|
count:N/M | Round-robin by test count |
hash:N/M | Stable hash (same test → same shard) |
Output & Reporting
| Option | Effect |
|---|
--status-level all | Show every test’s status |
--failure-output immediate | Print failures as they happen |
--message-format libtest-json | Machine-readable output |
--profile ci | Use CI-tuned settings |
| JUnit output | Configure in nextest.toml for CI reporting |
Limitations
| Not supported | Why |
|---|
| Doctests | Run separately with cargo test --doc |
#[bench] | Use criterion instead |
| Some libtest flags | Different runner semantics |
A common CI pattern is cargo nextest run && cargo test --doc.
nextest vs cargo test
| Aspect | cargo nextest | cargo test |
|---|
| Process model | One per test | One per binary |
| Isolation | Strong | Shared within binary |
| Speed | 2–3x faster typical | Baseline |
| Flaky detection | Built-in | None |
| CI sharding | Built-in | Manual |
| Doctests | No | Yes |
Resources