Tox Testing Guide
This guide covers using tox for automated testing across multiple Python environments.
Table of Contents
What is Tox?
Tox is a command-line tool that automates and standardizes testing in Python. It:
Tests across multiple Python versions (3.12, 3.13, 3.14, 3.15)
Creates isolated environments for each test run
Automates quality checks (linting, type checking, formatting)
Simulates CI/CD pipelines locally before pushing code
Manages dependencies consistently across environments
Quick Start
Installation
Tox is included in the development dependencies:
# Install with dev dependencies
pip install -e ".[dev]"
# Or install tox separately
pip install tox
Basic Usage
# Run all default test environments
tox
# List all available environments
tox list
# Run in parallel (faster!)
tox -p auto
# Run specific environment
tox -e py312
Available Environments
Default Environments (11)
These run when you execute tox without arguments:
Environment |
Python Version |
Description |
|---|---|---|
|
3.12 |
Run tests with Python 3.12 |
|
3.13 |
Run tests with Python 3.13 |
|
3.14 |
Run tests with Python 3.14 |
|
3.15 |
Run tests with Python 3.15 |
|
(any) |
Run ruff linter |
|
(any) |
Run mypy type checker |
|
(any) |
Check code formatting with ruff |
|
(current) |
Run tests with coverage reporting |
|
(any) |
Run security audit with pip-audit |
Total: 11 default testenvs
Additional Environments (15)
These are available but don’t run by default:
Environment |
Description |
Command |
|---|---|---|
|
Run unit tests only |
|
|
Run integration tests only |
|
|
Auto-format code with ruff |
|
|
Run all checks before commit |
|
|
Build Sphinx documentation |
|
|
Build and serve docs locally |
|
|
Remove build artifacts |
|
|
Build distribution packages |
|
|
Run the NHL Scrabble analyzer |
|
|
Simulate full CI pipeline |
|
|
Quick test run (no coverage) |
|
|
Run tests in watch mode |
|
|
Publish to TestPyPI |
|
|
Publish to PyPI (caution!) |
|
|
Display package version |
|
Total: 15 additional testenvs
Grand Total: 26 testenvs (11 default + 15 additional)
Common Usage Patterns
Pre-Commit Workflow
Before committing code, verify everything works:
# Option 1: Run quality checks and tests
tox -e quality,py312
# Option 2: Use the comprehensive check environment
tox -e check
# Option 3: Simulate full CI pipeline
tox -e ci
Testing Across Python Versions
# Test against all Python versions
tox -e py312,py313,py314,py315
# Test in parallel (much faster!)
tox -p auto -e py312,py313,py314,py315
# Test specific version only
tox -e py312
tox -e py315
Code Quality Checks
# Run linter only
tox -e ruff-check
# Run type checker only
tox -e mypy
# Check code formatting
tox -e ruff-format
# Run all quality checks together
tox -e quality
# Auto-fix formatting issues
tox -e format-fix
Coverage Reporting
# Generate coverage report
tox -e coverage
# View in browser (opens htmlcov/index.html)
# The coverage command prints the file:// URL at the end
Running the Application
# Run the analyzer through tox
tox -e run
# Run with arguments
tox -e run -- --verbose
tox -e run -- --format json --output report.json
Cleaning and Rebuilding
# Clean all tox environments
tox -e clean
# Recreate environments (useful after dependency changes)
tox -r
# Recreate specific environment
tox -e py312 -r
# Remove .tox directory entirely
rm -rf .tox/
Makefile Integration
All tox commands are available through the Makefile for convenience. The Makefile now uses a dynamic pattern rule (tox-%) that automatically handles any tox environment.
Basic Testing
make tox # Run all default environments
make tox-parallel # Run in parallel
make tox-list # List all environments
make tox-envs # List all environments (alternative)
Python Version Testing
The Makefile uses a dynamic pattern rule that automatically handles any Python version:
# Via Makefile (dynamic pattern rule - automatically handled)
make tox-py312 # Test Python 3.12
make tox-py313 # Test Python 3.13
make tox-py314 # Test Python 3.14
make tox-py315 # Test Python 3.15
make tox-py316 # Future Python 3.16 (will work automatically!)
# Or use tox directly:
tox -e py312 # Test Python 3.12
tox -e py313 # Test Python 3.13
tox -e py314 # Test Python 3.14
tox -e py315 # Test Python 3.15
Quality Checks
Quality check targets are now handled by the dynamic pattern rule:
# Via Makefile (dynamic pattern rule - automatically handled)
make tox-ruff-check # Run linter
make tox-mypy # Run type checker
make tox-coverage # Generate coverage report
make tox-quality # All quality checks
# Or use tox directly:
tox -e ruff-check # Run linter
tox -e mypy # Run type checker
tox -e coverage # Generate coverage report
CI Simulation
make ci # Simulate CI pipeline (traditional)
make tox-ci # Simulate CI with tox (via dynamic pattern rule)
# Or use tox directly:
tox -e ci # Simulate full CI pipeline
Maintenance
make tox-clean # Clean tox environments
make tox-recreate # Recreate all environments
Dynamic Pattern Rule Benefits
The tox-% pattern rule provides:
Automatic support for any tox environment
Future-proof - new Python versions work automatically
No maintenance - add environments to
tox.ini, Makefile works automaticallyDiscoverable - use
make tox-envsto see all available environments
Configuration
tox.ini
The tox configuration is in tox.ini at the project root. Key sections:
[tox]
# Python versions to test
envlist = py{312,313,314,315}, ruff-check, mypy, ruff-format, coverage, pip-audit
# Shared settings
minversion = 4.0
isolated_build = true
skip_missing_interpreters = true
Customizing Environments
To modify an environment, edit tox.ini:
[testenv:coverage]
description = Run tests with coverage reporting
deps = {[testenv]deps}
commands =
pytest --cov=nhl_scrabble --cov-fail-under=80
Adding New Environments
Add a new section to tox.ini:
[testenv:myenv]
description = My custom environment
deps =
pytest
commands =
pytest -k my_test
Troubleshooting
Python Version Not Available
If you see “InterpreterNotFound”:
# Check which Python versions are installed
python3.12 --version
python3.13 --version
python3.14 --version
python3.15 --version
# Skip missing interpreters (configured by default)
tox --skip-missing-interpreters
# Or test only available versions
tox -e py312 # If you only have 3.12
tox -e py315 # If you only have 3.15
Dependency Conflicts
If you encounter dependency issues:
# Recreate the environment
tox -e py312 -r
# Or recreate all environments
tox -r
# Or delete and rebuild from scratch
rm -rf .tox/
tox
Out of Date Environments
After changing dependencies in pyproject.toml:
# Recreate all environments
tox -r
# Or for specific environment
tox -e py312 -r
Slow Test Runs
Speed up testing:
# Use parallel mode
tox -p auto
# Run only fast checks
tox -e fast
# Run specific environments
tox -e ruff-check,mypy # Skip actual test runs
Debugging Test Failures
# Run with verbose output
tox -e py312 -- -v
# Run with very verbose output
tox -e py312 -- -vv
# Run with output capture disabled
tox -e py312 -- -s
# Run specific test
tox -e py312 -- tests/unit/test_scrabble.py::test_specific
CI/CD Integration
GitHub Actions
Example workflow using tox:
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [''3.12', '3.13', '3.14', '3.15']
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install tox
run: pip install tox
- name: Run tests
run: tox -e py$(echo ${{ matrix.python-version }} | tr -d .)
GitLab CI
Example .gitlab-ci.yml:
test:
image: python:3.12
script:
- pip install tox
- tox -p auto
Local CI Simulation
Test exactly what CI will run:
# Simulate full CI pipeline
make tox-ci
# Or directly
tox -e ci
Advanced Usage
Running with Specific Options
Pass arguments to underlying commands:
# Pass pytest options
tox -e py312 -- -k test_scrabble -v
# Pass mypy options
tox -e mypy -- --strict
# Pass ruff options
tox -e ruff-check -- --fix
Environment Variables
Set environment variables for tox:
# Pass to specific environment
TOX_SKIP_ENV="py312|py312" tox
# Set environment variable for tests
tox -e py312 -- --env-var=NHL_SCRABBLE_VERBOSE=true
Combining Environments
Run multiple environments in sequence:
# Run quality checks then tests
tox -e quality,coverage
# Run for multiple Python versions
tox -e py312,py313,py314,py315
Parallel Execution
# Auto-detect number of CPUs
tox -p auto
# Specify number of parallel workers
tox -p 4
# Parallel with specific environments
tox -p auto -e py312,py313,py314,py315,ruff-check,mypy
Best Practices
Daily Development
# Quick iteration during development
pytest # Fast, use pytest directly
# Before committing
make tox-quality # Check code quality
# Before pushing
make tox-ci # Full CI simulation
Pre-Release Checklist
# 1. Run all tests across all Python versions
make tox-parallel
# 2. Check code quality
make tox-quality
# 3. Generate coverage report
make tox-coverage
# 4. Run security audit
tox -e security
# 5. Build distribution
tox -e build
Continuous Integration
Use
tox -p autofor faster CI runsCache the
.toxdirectory to speed up subsequent runsRun
tox -e ciwhich includes all checks
Resources
Project Contributing Guide
Summary
Key commands to remember:
# Quick reference
tox # Run all default environments
tox -p auto # Run in parallel (fastest)
tox -e ci # Simulate CI pipeline
tox -e py312 # Test specific Python version
tox -e quality # Run code quality checks
tox -e ruff-check # Run linter
tox -e mypy # Run type checker
tox -e coverage # Generate coverage report
tox -r # Recreate environments
tox list # List all available environments
For daily development, use the Makefile shortcuts:
make tox-parallel # Fastest multi-environment testing
make tox-ci # Pre-push verification (via dynamic pattern rule)
make tox-quality # Code quality checks (via dynamic pattern rule)
make tox-ruff-check # Run linter (via dynamic pattern rule)
make tox-mypy # Run type checker (via dynamic pattern rule)
make tox-envs # List all available tox environments
Note: Tox environments use tool-based names (ruff-check, mypy, ruff-format, pip-audit) for clarity.
Dynamic Pattern Rule: The Makefile uses a tox-% pattern rule that automatically handles any tox environment, making it future-proof and maintainable. Any environment you add to tox.ini will automatically work with make tox-<envname>.