testx is a universal test runner that auto-detects your project's language and framework, runs your tests, and displays clean, unified output. Zero configuration required.
Why testx?
| Without testx | With testx | |
|---|---|---|
| Rust | cargo test |
testx |
| Python | uv run pytest -v |
testx |
| Go | go test -v ./... |
testx |
| JavaScript | npx vitest run / npx jest |
testx |
| Java | mvn test / gradle test |
testx |
| Output | Different per language | Unified, beautiful |
| CI sharding | Manual config | --partition slice:1/4 |
| Flaky detection | Custom scripts | testx stress |
Features
- Auto-detection — Identifies language and test framework from project files
- 11 languages — Rust, Go, Python, JavaScript/TypeScript, Java, C/C++, Ruby, Elixir, PHP, .NET, Zig
- Multiple output formats — Pretty (default), JSON, JUnit XML, TAP
- CI sharding — Split tests across CI nodes with
--partition slice:1/4orhash:2/3 - Stress testing — Run tests N times to find flaky tests with
testx stress - Impact analysis — Only run tests affected by recent git changes with
--affected - Smart caching — Skip re-running tests when nothing changed with
--cache - Interactive picker — Fuzzy-search and pick specific tests with
testx pick - Watch mode — Re-run tests on file changes
- Retry logic — Automatically retry failing tests
- Parallel execution — Run multiple test suites concurrently
- Coverage integration — LCOV, Cobertura, JaCoCo, Go coverage
- Plugin system — Custom adapters (project-local and global), reporter plugins, shell hooks
- History tracking — Track test health scores, flaky tests, and trends over time
- Monorepo support — Scan and test all projects in a workspace with
testx workspace
Supported Languages
| Language | Frameworks | Package Managers |
|---|---|---|
| Rust | cargo test | — |
| Go | go test | — |
| Python | pytest, unittest, Django | uv, poetry, pdm, venv |
| JavaScript / TypeScript | Jest, Vitest, Mocha, AVA, Bun | npm, pnpm, yarn, bun |
| Java / Kotlin | Maven Surefire, Gradle | mvn, gradle |
| C / C++ | Google Test, CTest, Meson | cmake, meson |
| Ruby | RSpec, Minitest | bundler |
| Elixir | ExUnit | mix |
| PHP | PHPUnit | composer |
| C# / .NET / F# | dotnet test | dotnet |
| Zig | zig build test | — |
Installation
From crates.io (recommended)
npm
Install script (macOS / Linux)
|
From source
From releases
Download a prebuilt binary from the releases page.
Shell completions
# Bash
# Zsh
# Fish
# PowerShell
Quick Start
# Run tests in the current directory
# Run tests in a specific project
# Detect framework without running tests
# Pass extra arguments to the underlying runner
Usage
Output formats
CI sharding
Split tests across parallel CI jobs:
# Slice-based (deterministic, ordered)
# Hash-based (stable across test additions)
GitHub Actions example:
jobs:
test:
strategy:
matrix:
shard:
steps:
- run: testx --partition slice:${{ matrix.shard }}/4
Flaky test detection
# Run tests 10 times (default)
# Run 50 iterations, stop on first failure
# Cap total time at 60 seconds
# Require all tests to have ≥90% pass rate
Output includes severity classification and timing statistics:
Stress Test Report: 20/20 iterations in 15.16s
Flaky tests detected (4):
🔴 [CRITICAL] timing_lock_acquisition (6/20 passed, 30.0% pass rate)
🟠 [HIGH] network_timeout (12/20 passed, 60.0% pass rate)
🟡 [MEDIUM] temp_dir_collision (16/20 passed, 80.0% pass rate)
🟢 [LOW] rare_gc_pause (49/50 passed, 98.0% pass rate)
Timing Statistics:
Mean: 757.8ms | Median: 753.2ms | Std Dev: 89.9ms
P95: 892.0ms | P99: 906.8ms | CV: 0.12
Severity levels: Critical (<50%), High (50–80%), Medium (80–95%), Low (>95%).
Impact analysis
Only run tests when relevant source files changed:
# Skip tests if only docs changed
# Analyze what changed without running
# Compare against a branch
Smart caching
# Skip re-running if source files haven't changed
# Clear the cache
Monorepo / workspace
Scan a monorepo and run tests across all detected projects:
# Discover and test all projects
# List projects without running
# Only test Rust and Python projects
# Include directories normally skipped (e.g., packages/)
# Run sequentially instead of in parallel
Test history & analytics
Track test health over time:
# Quick overview
# Flaky test report
# Slowest tests trend
# Health score dashboard (A–F grading)
# Last 50 runs
Interactive test picker
Fuzzy-search through all discovered tests, select one or more, and run only those.
Other options
Configuration
Create a testx.toml in your project root (or run testx init):
# Override detected adapter
# adapter = "python"
# Extra arguments for the test runner
= ["-v", "--no-header"]
# Timeout in seconds (0 = no timeout)
= 60
# Environment variables
[]
= "true"
CLI flags always override config file values.
Plugin System
Custom adapters
Define custom test runners in testx.toml:
[[]]
= "my-framework"
= "my-config.json" # Simple: single file trigger
= "my-test-runner"
= ["--reporter", "json"]
= "json" # json | junit | tap | lines
= 0.8
= "my-test-runner --version" # Verify runner is installed
For advanced detection (multiple files, content matching, env vars):
[[]]
= "make-test"
= "make test"
= "lines"
= 0.85
[]
= ["Makefile", "test.mk"]
= ["make --version"]
= ["CI"]
= 2
[[]]
= "Makefile"
= "test:"
Global adapters
Place adapter definitions in ~/.config/testx/adapters/*.toml to make them available across all projects:
# ~/.config/testx/adapters/bazel.toml
= "bazel"
= "BUILD"
= "bazel test //..."
= "tap"
= 0.7
List adapters
Reporter plugins
Built-in reporters:
- Markdown — Generate markdown test reports
- GitHub Actions — Annotations with
::error::/::warning:: - HTML — Standalone HTML report
- Desktop notifications — System notification on completion
Building from Source
Running the test suite
Stats
| Metric | Value |
|---|---|
| Languages supported | 11 built-in + custom adapters |
| Test frameworks | 20+ |
| Source lines | ~36,000 |
| Test count | 1,150 (1,096 unit + 33 CLI + 21 integration) |
| Binary size (release) | ~2.2 MB |
| Framework detection | < 200 µs |
| Rust source files | 55 |
| Dependencies | minimal (clap, serde, colored, toml, anyhow, notify) |
| Clippy warnings | 0 |
Performance
testx adds negligible overhead on top of your test runner:
| Operation | Time |
|---|---|
| Config loading (no file) | ~1.4 µs |
| Config loading (with testx.toml) | ~18 µs |
| Framework detection (single lang) | ~67–83 µs |
| Framework detection (polyglot) | ~149 µs |
| Detect + parse 100 tests (Rust) | ~138 µs |
| Detect + parse 100 tests (Python) | ~161 µs |
| Detect + parse 100 tests (Go) | ~173 µs |
| Parse 1,000 tests (Rust) | ~570 µs |
| Parse 5,000 tests (Rust) | ~3 ms |
| JSON serialization (1,000 tests) | ~422 µs |
Total testx overhead: < 1 ms for typical projects. Run cargo bench --bench overhead to reproduce.
Documentation
Full documentation is available at testx-cli.readthedocs.io.
Contributing
We welcome contributions! Please read these before getting started:
- Contributing Guide — Setup, workflow, and PR process
- Coding Guidelines — Architecture, code style, and module design
- Bug Report Template — Report a bug
- Feature Request Template — Suggest a feature
Pull requests are reviewed against the PR template checklist.