DEV Community

schettino72
schettino72

Posted on

rut: A Python Test Runner That Skips Unaffected Tests

Nothing bugs me more than waiting for the computer to do something I already know is pointless. Changed one file and watching 500 unrelated tests run? That's wasted time I'm not getting back.

In 2008, I created doit — a build tool that tracks file dependencies and only rebuilds what changed. Same idea as make, but for Python workflows.

Then I built pytest-incremental — applying the same principle to tests. If you change utils.py, only run tests that depend on it. Skip the rest.

Now there's rut.

Why another test runner?

pytest-incremental requires pytest. Its plugins are great individually, but combining multiple plugins into a consistent experience is hard — they step on each other, configuration gets fragile, and debugging interactions is painful.

Codebases have grown orders of magnitude, and AI-assisted workflows are accelerating that further. We need new test infrastructure to keep up. Parallelization helps, but fast turnaround is still king — skipping what doesn't need to run beats running it faster.

rut is simple:

pip install rut

rut              # run all tests, build dependency graph
rut --changed    # run only affected tests
Enter fullscreen mode Exit fullscreen mode

How it works

rut analyzes your import graph. If api.py imports models.py which imports utils.py, and you change utils.py, rut knows to run tests for all three.

Tests for modules that don't depend on utils.py? Skipped.

For well-structured codebases, this typically means 50-80% fewer tests on incremental runs.

Read more: Dependency Ordering | Incremental Testing

Features

  • Dependency-aware ordering: foundational tests run first, so failures point to root causes
  • Async support: built-in, no plugins needed
  • --dry-run: see what would run without running it
  • unittest compatible: drop-in replacement for python -m unittest

Try it

pip install rut
rut
Enter fullscreen mode Exit fullscreen mode

GitHub

Top comments (0)