Tox
02 / 02

CI Integration & Why Isolation Matters

tox: CI Integration & Why Isolation Matters

GitHub Actions Integration

# .github/workflows/test.yml
name: Test
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ['3.9', '3.10', '3.11', '3.12']
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
      - run: pip install tox tox-gh-actions
      # tox-gh-actions auto-maps the CI job's Python version to the
      # matching tox environment -- no manual mapping needed
      - run: tox

# tox-gh-actions.ini (or a [gh-actions] section in tox.ini) declares
# the mapping tox-gh-actions reads:
# [gh-actions]
# python =
#   3.9: py39
#   3.10: py310
#   3.11: py311
#   3.12: py312, lint

Same Config, Local and CI

  • A pure CI matrix (strategy.matrix.python-version with no tox) only solves multi-version testing IN CI -- reproducing a specific version's local failure means manually managing that Python install/virtualenv.

  • tox centralizes the environment definitions -- the same tox.ini serves both `tox -e py311` run locally and the CI job invoking the same command.

  • Avoids duplicated/drifting test-invocation logic between "what a developer runs locally" and "what CI actually runs".

Why Isolation Catches Real Bugs

  • A developer's local environment can have stray packages from unrelated work masking a real dependency-declaration bug.

  • A published library's classifiers claiming "supports Python 3.9-3.12" is only trustworthy if actually verified per version -- tox's environment matrix is how many maintainers make that claim credible before release.

  • tox is test-runner-agnostic -- commands can invoke pytest, unittest, or anything else; pytest is just the common convention, not a tox requirement.

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free