nox: Python Test Automation Tool
nox manages Python virtual environments and runs tests across multiple Python versions and configurations. Where tox uses declarative TOML or INI configuration, nox uses Python code in a noxfile.py, which makes it straightforward to express conditionals, loops, and dynamic session generation. Hatch offers a third approach with its environment matrix system configured in pyproject.toml.
When to Use nox
nox solves the problem of running test suites, linters, and other checks across multiple Python versions and dependency combinations. Choose nox over tox when test automation logic requires conditionals, loops, or dynamic session generation that declarative configuration cannot express. Projects with straightforward multi-version testing may find uv’s built-in multi-version support sufficient without a separate tool; see Do you still need tox or nox if you use uv? for guidance.
Key Features
- Python-based configuration: test sessions are defined as functions in a
noxfile.py, with full access to conditionals, loops, and dynamic session generation - Session dependencies: the
requiresparameter lets a session declare that other sessions must run first - uv backend: set
venv_backend='uv'(or'uv|virtualenv'for fallback) to use uv for environment creation and package installation - pyproject.toml helpers:
nox.project.load_toml(),nox.project.dependency_groups(), andnox.project.python_versions()read dependency and version data frompyproject.tomlso the noxfile stays in sync with project metadata - PEP 723 noxfile dependencies: noxfiles can declare their own dependencies using inline script metadata, so plugins and helper libraries install automatically
- Multi-version testing: runs sessions against multiple Python versions
- Parallel execution: runs sessions concurrently with
--parallelto speed up CI - Parametrization: reuses session logic across configurations with
@nox.parametrize
Configuration
Sessions are defined with the @nox.session decorator:
import nox
@nox.session(python=["3.11", "3.12", "3.13", "3.14"])
def tests(session):
session.install("pytest")
session.run("pytest")Set defaults at the module level with nox.options:
nox.options.default_venv_backend = "uv"
nox.options.reuse_venv = "yes"Session dependencies
A session can require other sessions to run first:
@nox.session
def lint(session):
session.install("ruff")
session.run("ruff", "check", ".")
@nox.session(requires=["lint"])
def tests(session):
session.install("pytest")
session.run("pytest")Reading from pyproject.toml
nox.project provides helpers that keep the noxfile in sync with project metadata:
import nox
pyproject = nox.project.load_toml("pyproject.toml")
@nox.session(python=nox.project.python_versions(pyproject))
def tests(session):
session.install(*nox.project.dependency_groups(pyproject, "test"))
session.run("pytest")Basic Usage
# Run all default sessions
nox
# Run a specific session
nox -s tests
# Run sessions matching a tag
nox -t lint
# Run sessions in parallel
nox --parallel
# List available sessions
nox --listPros
- Python-based configuration handles logic that declarative formats cannot express
- Session dependencies (
requires) let complex pipelines run in the right order - uv backend integration for fast environment creation and installs
nox.projecthelpers keep the noxfile in sync withpyproject.tomlmetadata- Active maintenance with calendar-versioned releases
Cons
- Requires Python knowledge to configure effectively
- Less standardized than tox in the Python ecosystem
- More setup than needed for projects with simple multi-version testing
Learn More
- How to test against multiple Python versions using uv
- Do you still need tox or nox if you use uv?
- pytest reference page
- tox reference page
- uv reference page
- nox Documentation
- nox Configuration & API
- GitHub Repository