Running Rust Tests Faster With Cargo Nextest in CI
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.

cargo test runs the tests of one binary in threads, and the binaries one after another. For a workspace with many crates, that leaves cores idle. cargo-nextest is a different runner that schedules all tests across the machine and gives each its own process. The output is also easier to read. This post covers installing, the config you actually need and what it does not do. It supports the CI advice in the testing in Rust guide.
cargo-nextest 0.9, Rust 1.90.
Install and run
cargo install cargo-nextest --locked
cargo nextest runOutput has this shape, with your own names and numbers:
Starting 142 tests across 8 binaries
PASS [ 0.012s] core parser::tests::parses_header
PASS [ 0.031s] api routes::list_users
Summary [ 2.115s] 142 tests run: 142 passed, 0 skippedEach line shows the duration of one test, and slow tests are flagged. On a suite with many small binaries, the wall clock time often drops, because the cores stay busy; the amount depends on your suite. Measure both runners on your project with time.
Configuration
[profile.default]
fail-fast = false
slow-timeout = { period = "30s", terminate-after = 4 }
[profile.ci]
retries = 2
fail-fast = false
test-threads = 4
[profile.ci.junit]
path = "junit.xml"Use cargo nextest run --profile ci in CI. slow-timeout marks tests slower than 30 seconds and terminates a hung test after four periods. retries = 2 reruns a failing test up to twice and marks it FLAKY if it later passes. junit.xml feeds CI dashboards.
Isolation, for better and worse
Because each test is its own process:
- A global
staticinitialized by one test does not leak to the next. Order dependencies surface as failures. - A test calling
std::process::exitor aborting fails alone. - Per-process setup runs for every test, so expensive setup (starting a container) is repeated; use a wrapper script or a setup script defined in the config to share it.
That is the main behavior change if a suite uses once_cell or lazy_static shared state to avoid repeated setup.
Filtering
cargo nextest run -E 'package(core) and test(parser)'
cargo nextest run --run-ignored ignored-onlyThe filter expression language selects by package, binary, test name and more. Compare with name filters in ignoring and filtering tests.
Splitting across machines
cargo nextest run --partition count:1/3Run 1/3, 2/3 and 3/3 on three CI jobs to split the work. Archive the build once with cargo nextest archive and run it elsewhere without recompiling.
Doc tests
cargo nextest run && cargo test --docNextest does not run doc tests, because rustdoc compiles and runs them in a way the runner cannot intercept. Keep the second command in CI (doc tests).
Limits
For a small crate with a few dozen fast tests, cargo test is just as quick and needs nothing installed. Retry settings can mask real bugs; read flaky tests before turning them on. The tool's documentation is at nexte.st.


