tox
tox is a generic virtual environment management and test command-line tool for Python projects. It automates and standardizes testing across various Python versions, interpreters, and dependency configurations, serving as a powerful frontend for local development and Continuous Integration servers. Currently at version 4.51.0, tox maintains an active development pace with frequent patch and minor releases, often on a monthly or bi-weekly cadence.
Warnings
- breaking Upgrading from tox 3 to tox 4 involves significant breaking changes due to a ground-up rewrite. Key changes include the CLI command structure (e.g., `tox run -e` instead of `tox -e`), stricter INI parsing rules (e.g., `#` is always a comment, `pass_env` requires comma/newline separators), removal of `-U` in `deps`, and a completely new plugin API. Environment names matching new `tox 4` subcommands can also lead to ambiguity.
- gotcha tox environments are often reused for performance. However, tox does not always detect changes in `setup.py` or `requirements.txt` files that define package dependencies. This can lead to stale virtual environments where tests run against outdated dependencies.
- gotcha By design, tox environments are isolated and do not inherit host system environment variables unless explicitly configured. This can cause commands to fail if they rely on external environment variables (e.g., API keys, build flags) that are not passed through.
- gotcha tox supports multiple configuration files (`pyproject.toml` (native TOML), `tox.toml`, `pyproject.toml` (legacy INI via `legacy_tox_ini`), `tox.ini`, `setup.cfg`) with a specific precedence order. Mixing configuration styles or placing core settings in environment-specific sections can lead to ignored or unexpected behavior. TOML is the recommended format for new projects as of tox 4, offering more robustness, but INI remains supported.
Install
-
pip install tox
Quickstart
import os
# Create a dummy project structure
os.makedirs('my_package/tests', exist_ok=True)
with open('my_package/main.py', 'w') as f:
f.write('def add(a, b):\n return a + b')
with open('my_package/tests/test_main.py', 'w') as f:
f.write('from my_package.main import add\n\ndef test_add():\n assert add(1, 2) == 3')
# Create pyproject.toml for tox configuration
with open('pyproject.toml', 'w') as f:
f.write('''
[project]
name = "my_package"
version = "0.1.0"
[tool.tox]
env_list = ["py", "lint"]
[tool.tox.env_run_base]
description = "Run the test suite with pytest"
deps = ["pytest>=8"]
commands = ["pytest {posargs:tests}"]
[tool.tox.env.lint]
description = "Run linters"
skip_install = true
deps = ["ruff"]
commands = ["ruff check {posargs:.}"]
''')
print("Project setup complete. Now run 'tox' in your terminal.")