Skip to content

Do you still need tox or nox if you use uv?

Before uv, setting up multi-version testing meant installing Python interpreters by hand, configuring pyenv, and hoping tox found them all. uv removes that friction: uv run --python 3.12 pytest downloads Python 3.12 if it’s missing and runs your tests in one command. Teams that discover this often ask whether tox or nox are still worth the dependency.

The short answer: uv replaces the plumbing (Python installs, virtual environment creation, dependency installation), not the orchestration. Whether you still need an orchestrator depends on what you’re asking it to do.

What uv handles on its own

For a project that needs the same test suite run across a few Python versions, a shell loop is enough:

for version in 3.10 3.11 3.12 3.13; do
    uv run --python $version pytest
done

uv downloads any missing Python versions automatically. A justfile recipe captures this for the whole team:

test-matrix:
    #!/usr/bin/env bash
    set -e
    for version in 3.10 3.11 3.12 3.13; do
        echo "=== Python $version ==="
        uv run --python $version pytest
    done

This covers the most common case: verifying that your library doesn’t break across the Python versions declared in requires-python. See How to test against multiple Python versions using uv for a complete walkthrough.

When tox or nox still earn their place

A shell loop runs the same environment repeatedly with different Python versions. That breaks down when the matrix has more dimensions:

  • Dependency combinations: testing against both lowest and highest supported versions of a dependency, or against multiple extras configurations
  • Non-test environments: running linting, type checking, documentation builds, or package builds as isolated, reproducible environments
  • Parallel execution: tox’s --parallel flag and nox’s --sessions filter let you run environments concurrently and selectively in CI without writing custom bash
  • Shared environment caches: both tools reuse existing environments when nothing has changed, rather than recreating from scratch on every run

Library maintainers with a full test matrix (multiple Python versions × multiple dependency versions × multiple extras) hit these limits quickly. An application team deploying a single Python version to production rarely does.

tox with uv: keep the workflow, drop the wait

The tox-uv plugin drops uv’s resolver and installer into tox as a replacement for pip and virtualenv. The tox.ini stays the same; environment creation and dependency installation just happen faster. On a project with a dozen test dependencies and four Python versions, tox-uv with --parallel can cut a full matrix run from minutes to seconds.

tox-uv also exposes uv’s lowest resolution strategy, which is otherwise awkward to automate:

[testenv:lowest]
uv_resolution = lowest
deps = pytest
commands = pytest {posargs}

This environment installs the oldest compatible version of every dependency, catching breakage that highest resolution masks. See How to use uv to speed up tox for setup instructions.

nox with uv: Python-scripted flexibility

nox uses a noxfile.py instead of INI configuration, which makes complex test logic easier to read and maintain. nox has a native uv backend that handles environment creation and Python discovery:

import nox

@nox.session(python=["3.10", "3.11", "3.12", "3.13"], venv_backend="uv")
def tests(session):
    session.install("pytest")
    session.run("pytest")

Setting venv_backend="uv" tells nox to use uv for virtual environment creation and package installation. Like tox-uv, this delegates Python version downloads to uv when the requested version is not installed locally.

nox suits teams that prefer Python over INI for configuration, or that have noxfiles already parameterized with complex session logic.

Choosing an approach

Scenario Approach
Same tests, multiple Python versions uv run --python X.Y pytest loop or justfile
Multiple Python versions in CI Shell loop in GitHub Actions matrix
Multiple dependency configurations tox with tox-uv
Parallel environments, shared CI caching tox with tox-uv
Lowest-version compatibility testing tox with tox-uv (uv_resolution = lowest)
Complex environment logic, team prefers Python config nox with uv backend
Existing tox or nox project Add tox-uv or enable nox’s uv backend; keep everything else

Learn More

Last updated on

Please submit corrections and feedback...