Skip to content

A .NET global tool that wraps dotnet test, captures TRX results, tracks test history, and displays regression charts

License

Notifications You must be signed in to change notification settings

asynkron/Asynkron.TestRunner

Repository files navigation

Asynkron.TestRunner

Asynkron.TestRunner

A .NET global tool that wraps dotnet test, captures TRX results, tracks test history, and displays regression charts.

Features

  • Wraps dotnet test and streams output in real-time
  • Automatically captures TRX test results
  • Tracks test history per project and command signature
  • Shows pass/fail bar charts across runs
  • Detects regressions (tests that passed before but now fail)
  • Detects fixes (tests that failed before but now pass)
  • Supports color and non-color (CI/piped) output modes
  • Default 20s per-test timeout (detects and reports hung tests)
  • Automatic hang isolation - when a hang is detected, automatically drills down to find the culprit
  • Displays test hierarchy tree using Spectre.Console for better visualization
  • Easy filter syntax for running specific tests

Installation

dotnet tool install -g Asynkron.TestRunner

Usage

Run all tests

testrunner                  # Runs: dotnet test

Run filtered tests

testrunner "MyClass"        # Runs: dotnet test --filter "FullyQualifiedName~MyClass"
testrunner "Namespace.Test" # Matches any test containing that pattern

Custom command

testrunner -- dotnet test ./tests/MyTests
testrunner -- dotnet test --filter "Category=Unit"

List tests (without running)

testrunner list                 # List all tests
testrunner list "Storage"       # List tests matching 'Storage'

Options

testrunner --timeout 60 "SlowTests"   # 60s hang timeout (default: 20s)
testrunner --timeout 0                 # Disable hang detection
testrunner --help                      # Show help

View history

testrunner stats                                    # Default command history
testrunner stats -- dotnet test ./tests/MyTests     # Specific command history
testrunner stats --history 5                        # Last 5 runs

Automatic hang isolation

When a test hang is detected during a normal run, testrunner automatically isolates and finds the hanging test:

testrunner "MyTests"                # If hang detected, auto-isolates

The isolation process:

  1. Displays a tree of all matching tests
  2. Breaks the tree into branches with fewer than 100 leaf tests (or the full tree if smaller)
  3. Runs each branch separately with the hang timeout and reports failing or hanging branches

Manual isolate command

You can also manually trigger isolation:

testrunner isolate                  # Find hanging test in all tests
testrunner isolate "language"       # Find within tests matching 'language'
testrunner isolate --timeout 60     # Use 60s timeout (default: 30s)
testrunner isolate --parallel 4     # Run up to 4 batches concurrently
testrunner isolate -p               # Use all CPU cores for parallel batches

Parallel Isolation

For large test suites, parallel isolation can significantly speed up the process:

testrunner isolate -p 4 "Tests"     # Run 4 test batches concurrently
testrunner isolate --parallel       # Auto-detect parallelism (CPU count)

Parallel mode:

  • Runs independent test batches concurrently
  • Uses a semaphore to limit concurrent processes
  • Thread-safe console output with progress indicators
  • Falls back to sequential drilling when hanging tests are found

View regressions

testrunner regressions      # Compare last 2 runs

Clear history

testrunner clear

Example Output

After a test run with regressions:

FAILED
──────────────────────────────────────────────────
  Passed:  132
  Failed:  4
  Skipped: 0
  Total:   136
  Duration: 2.3s
  Pass Rate: 97.1%

Regressions (3):
  ✗ MyTests.SomeTest.ThatUsedToPass
  ✗ MyTests.AnotherTest.NowFailing
  ✗ MyTests.ThirdTest.Broken

History chart:

Test History (4 runs)
──────────────────────────────────────────────────────────────────────
2025-12-30 10:04  █████████████████████████████X  135/136 (99.3%)  ✗1
2025-12-30 10:03  █████████████████████████████X  132/136 (97.1%)  ✗4
2025-12-30 10:00  █████████████████████████████X  135/136 (99.3%)  ✗1
2025-12-30 10:00  █████████████████████████████X  135/136 (99.3%)  ✗1

Configuration Options

Timeout Options

Option Description
-t, --timeout <seconds> Per-test hang timeout (default: 20s for run, 30s for isolate)
--timeout 0 Disable hang detection entirely

Isolate Options

Option Description
-t, --timeout <seconds> Per-test timeout during isolation (default: 30s)
-p, --parallel [N] Run N batches in parallel (default: 1, or CPU count if no N)

Filter Patterns

Filters use FullyQualifiedName~<pattern> matching:

testrunner "MyClass"            # Matches: MyNamespace.MyClass.AnyTest
testrunner "Integration"        # Matches all tests containing "Integration"
testrunner "Tests.Unit"         # Matches: MyApp.Tests.Unit.*

How History is Tracked

History is stored in .testrunner/ and is tracked separately by:

  • Project - hash of git repo root (or current directory)
  • Command signature - hash of the test command (path + filters)

This means:

  • Different repos have separate histories
  • --filter A and --filter B have separate histories
  • Running the same command compares correctly

License

MIT

About

A .NET global tool that wraps dotnet test, captures TRX results, tracks test history, and displays regression charts

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages