Skip to main content

Command Palette

Search for a command to run...

cargo-nextest: Faster Rust Testing with Better Output

Published
5 min read
D
Practical guides for developers: TypeScript, developer tools, CI/CD, and modern web development. We cover the tools that make devs more productive.

cargo test is built into Rust's toolchain and works well for simple cases. But as your project grows — more tests, slower builds, flaky network tests, CI that needs structured output — cargo test's limitations become friction. cargo-nextest is a replacement that runs tests faster, presents output more clearly, and integrates better with CI systems.

Why nextest

The headline number: nextest typically runs Rust test suites 2–3× faster than cargo test. This happens because nextest runs each test as its own process, enabling true parallelism. cargo test uses threads within a single process, which limits parallelism when tests share global state or block on I/O.

Other improvements:

  • Structured output — test results as a clean table, not a wall of text
  • Progress bar — see how many tests passed/failed/running in real time
  • Test retries — automatically retry flaky tests, configurable per-test
  • Partitioning — split tests across multiple CI machines
  • JUnit XML output — CI systems can parse and display results
  • Slow test detection — flag tests that exceed a time threshold

Installation

# Via cargo-binstall (fastest — downloads precompiled binary)
cargo binstall cargo-nextest

# Or via cargo install
cargo install cargo-nextest --locked

# Or download binary directly
curl -LsSf https://get.nexte.st/latest/linux | tar zxf - -C ~/.cargo/bin

Verify:

cargo nextest --version

Basic Usage

# Run all tests (replaces cargo test)
cargo nextest run

# Run tests matching a filter
cargo nextest run auth

# Run tests in a specific package
cargo nextest run -p my-crate

# List tests without running
cargo nextest list

# Run with increased parallelism
cargo nextest run --test-threads 16

The output looks different from cargo test:

    Finished test [unoptimized + debuginfo] target(s) in 2.34s
    Starting 47 tests across 3 test binaries

────────────── TESTS SKIPPED: 0 ──────────────────────────
────────────── TESTS PASSED: 47 ─────────────────────────

    Test run complete. 47 passed, 0 skipped, 0 failed in 1.823s

Each test result shows the test name, duration, and outcome. Failures include captured output.

Configuration

Configure nextest in .cargo/nextest.toml (or in Cargo.toml under [profile.nextest]):

[profile.default]
# Fail fast after N test failures
fail-fast = false

# Retry flaky tests up to 2 times
retries = 2

# Slow test threshold (print warning)
slow-timeout = { period = "30s", terminate-after = 3 }

# Maximum parallel threads
test-threads = "num-cpus"

[profile.ci]
# CI profile: JUnit output, no progress bar
retries = 2
failure-output = "final"
status-level = "all"
final-status-level = "all"

Run with a specific profile:

cargo nextest run --profile ci

Per-Test Configuration

Some tests need special handling — integration tests that hit a real database, tests that must run serially, tests known to be slow:

# .cargo/nextest.toml

[[profile.default.overrides]]
# Tests tagged as requiring serial execution
filter = 'test(#[serial])'
test-threads = 1

[[profile.default.overrides]]
# Database integration tests get more retries
filter = 'test(/integration/) and test(/database/)'
retries = 5

[[profile.default.overrides]]
# Known slow test — don't fail on slow threshold
filter = 'test(test_large_data_processing)'
slow-timeout = { period = "5m" }

The filter syntax supports test names, binary names, tags, and boolean operators.

CI Integration

GitHub Actions

name: Tests
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: dtolnay/rust-toolchain@stable

      - uses: taiki-e/install-action@cargo-nextest

      - name: Run tests
        run: cargo nextest run --profile ci

      - name: Upload JUnit results
        uses: mikepenz/action-junit-report@v4
        if: always()
        with:
          report_paths: 'target/nextest/ci/junit.xml'

Test Partitioning for Parallel CI

Split your test suite across multiple machines to run in parallel:

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        partition: [1, 2, 3, 4]
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: taiki-e/install-action@cargo-nextest

      - name: Run tests (partition ${{ matrix.partition }}/4)
        run: |
          cargo nextest run \
            --partition count:${{ matrix.partition }}/4 \
            --profile ci

Four machines run in parallel, each handling a quarter of the tests.

Filtering Syntax

nextest's filter syntax is powerful:

# Run tests with "auth" in the name
cargo nextest run auth

# Run tests in a specific binary
cargo nextest run --test integration_tests

# Exclude slow tests
cargo nextest run 'not test(slow)'

# Combine filters
cargo nextest run 'test(auth) and not test(network)'

# Run only doc tests (note: nextest doesn't run doc tests — use cargo test for those)

Known Limitations

nextest does not run doc tests (cargo test --doc). For projects that rely heavily on doctests for documentation examples, you'll need to run both:

cargo nextest run        # Unit and integration tests
cargo test --doc         # Doc tests only

This is tracked as a known limitation on the nextest GitHub. For most projects, running both in CI is straightforward.

nextest vs cargo test

Featurenextestcargo test
Speed2–3× fasterBaseline
Output formatStructured tableFlat text
Test isolationPer-processPer-thread
Flaky test retries
JUnit XML
CI partitioning
Doc tests
Standard toolchainNo (install required)Yes

For most Rust projects, nextest is worth adopting — the speed improvement alone justifies it, and better CI integration is a bonus. The only reason to stick with cargo test exclusively is if you depend heavily on doctests or can't add a binary dependency to your build.


Subscribe to DevTools Guide for more developer tool deep dives.

More from this blog

DevTools Guide

183 posts