Skip to content
Back to top

# Getting Started

This tutorial walks you through creating your first tox project from scratch. By the end, you will have a working tox configuration that runs tests and linting across multiple Python versions.

## Prerequisites

Before starting, make sure you have:

- Python 3.10 or later installed

- tox installed (see Installation)

- A Python project you want to test (or follow along to create one)

Verify tox is available:

    tox --version

## Creating your first configuration

tox needs a configuration file where you define what tools to run and how to set up environments for them. tox supports two configuration formats: TOML and INI. TOML is the recommended format for new projects – it is more robust, has proper type support, and avoids ambiguities inherent in INI parsing. INI remains supported for existing projects.

Create a `tox.toml` (or `tox.ini`) at the root of your project:

TOML

    env_list = ["3.13", "3.12", "lint"]

    [env_run_base]
    description = "run the test suite with pytest"
    deps = [
        "pytest>=8",
    ]
    commands = [["pytest", { replace = "posargs", default = ["tests"], extend = true }]]

    [env.lint]
    description = "run linters"
    skip_install = true
    deps = ["ruff"]
    commands = [["ruff", "check", { replace = "posargs", default = ["."], extend = true }]]

INI

    [tox]
    env_list = 3.13, 3.12, lint

    [testenv]
    description = run the test suite with pytest
    deps =
        pytest>=8
    commands =
        pytest {posargs:tests}

    [testenv:lint]
    description = run linters
    skip_install = true
    deps =
        ruff
    commands = ruff check {posargs:.}

Tip

You can also generate a `tox.ini` file automatically by running `tox quickstart` and answering a few questions.

## Understanding the configuration

The configuration has two parts: core settings and environment settings.

### Core settings

Core settings affect all environments or configure how tox itself behaves. They live at the root level in `tox.toml` (or under the `[tox]` section in `tox.ini`).

TOML

    env_list = ["3.13", "3.12", "lint"]

INI

    [tox]
    env_list = 3.13, 3.12, lint

The env_list setting defines which environments run by default when you invoke `tox` without specifying any. Both formats support generating environment matrices from factor combinations — INI uses curly-brace expansion (`3.{10-}`), while TOML composes from structured dicts. A single axis is a bare range dict (`{ prefix = "3.", start = 10 }`); multi-dimensional matrices use a `product` dict. See Generative environment list for details. For the full list of core options, see Core.

### Environment settings

Each tox environment has its own configuration. Settings defined at the base level (`env_run_base` in TOML, `testenv` in INI) are inherited by all environments unless overridden. Individual environments are configured under `env.<name>` in TOML or `testenv:<name>` in INI.

TOML

    [env_run_base]
    description = "run the test suite with pytest"
    deps = ["pytest>=8"]
    commands = [["pytest", { replace = "posargs", default = ["tests"], extend = true }]]

    [env.lint]
    description = "run linters"
    skip_install = true
    deps = ["ruff"]
    commands = [["ruff", "check", "."]]

INI

    [testenv]
    description = run the test suite with pytest
    deps =
        pytest>=8
    commands =
        pytest {posargs:tests}

    [testenv:lint]
    description = run linters
    skip_install = true
    deps =
        ruff
    commands = ruff check .

Here the `lint` environment overrides the base settings entirely, while `3.13` and `3.12` inherit from the base.

Tip

Options must go in the correct section — placing a core option in an environment section (or vice versa) silently has no effect. Run `tox run -v` or `tox config` to check for misplaced keys.

### Environment names and Python versions

Environment names can consist of alphanumeric characters, dashes, and dots. Names are split on dashes into factors – for example `py311-django42` splits into factors `py311` and `django42`. Additionally, the current platform (like `linux`, `darwin`, `win32`) is automatically available as an implicit factor for conditional configuration.

tox recognizes certain naming patterns and automatically sets the Python interpreter:

- `N.M`: CPython N.M (e.g. `3.13`) – preferred

- `pyNM` or `pyN.M`: CPython N.M (e.g. `py313` or `py3.13`) – legacy, still supported

- `pypyNM`: PyPy N.M

- `cpythonNM`: CPython N.M

- `graalpyNM`: GraalPy N.M

Prefer the `N.M` form (e.g. `3.14`) over `pyNMM` (e.g. `py314`). The dotted form is unambiguous, reads more naturally in environment lists and CI output, and avoids confusion for Python versions >= 3.10 where the concatenated digits become three characters.

Note

Version-number factors like `3.14` can be checked in conditional expressions using subscript syntax: `factor['3.14']` (the dot-syntax `factor.3.14` would be a syntax error). See Conditional value reference for details.

If the name doesn’t match any pattern, tox uses the same Python as the one tox is installed into (this is the case for `lint` in our example). To override this fallback, set default_base_python:

    [env_run_base]
    default_base_python = ["3.14", "3.13"]

This pins a default Python version for environments without a Python factor, improving reproducibility across machines with different system Pythons.

Tip

If your project uses PEP 751 lock files (`pylock.toml`), you can install locked dependencies via pylock instead of listing packages in `deps`.

For the full list of environment options, see tox environment.

### Scaling to multiple Python versions

When your test matrix grows beyond a few environments, use `env_base` sections to define named templates that generate environments from factor combinations:

    [env_base.test]
    factors = [["3.13", "3.14"]]
    deps = ["pytest>=8"]
    commands = [["pytest"]]

This generates `test-3.13` and `test-3.14`, each inheriting deps and commands from the template. The template itself inherits from `env_run_base`, so global defaults still apply. See Environment base templates for details.

## Running your environments

Run all default environments (those listed in env_list):

    tox

Run a specific environment:

    tox run -e lint

Run multiple environments:

    tox run -e 3.13,lint

Pass extra arguments to the underlying tool using `--`:

    # Run pytest in verbose mode
    tox run -e 3.13 -- -v

    # Run ruff on a specific file
    tox run -e lint -- src/mymodule.py

The `{ replace = "posargs" }` in TOML (or `{posargs}` in INI) is a placeholder that gets replaced by whatever you pass after `--`.

## Understanding the output

On the first run, tox creates virtual environments and installs dependencies. Subsequent runs reuse existing environments unless dependencies change:

    $ tox run -e 3.13,lint
    3.13: install_deps> python -m pip install 'pytest>=8'
    3.13: commands[0]> pytest tests
    ========================= 3 passed in 0.12s =========================
    3.13: OK ✔ in 5.43s
    lint: install_deps> python -m pip install ruff
    lint: commands[0]> ruff check .
    All checks passed!
    lint: OK ✔ in 2.11s

      3.13: OK (5.43=setup[3.21]+cmd[2.22] seconds)
      lint: OK (2.11=setup[1.05]+cmd[1.06] seconds)
      congratulations :)

tox will automatically detect changes to your dependencies and recreate environments when needed. You can force a full recreation with the `-r` flag:

    tox run -e 3.13 -r

If tools inside the environment maintain their own caches (e.g. pre-commit), you can use recreate_commands to clean them before the environment directory is removed. See Clean external caches during recreation for details.

If you want to rerun tests without reinstalling dependencies or the package (e.g. when working offline or when nothing has changed), use `--skip-env-install`:

    tox run -e 3.13 --skip-env-install

## Listing available environments

See all configured environments and their descriptions:

    $ tox list
    default environments:
    3.13 -> run the test suite with pytest
    3.12 -> run the test suite with pytest
    lint -> run linters

## Inspecting configuration

View the resolved configuration for an environment:

    tox config -e 3.13 -k deps commands

The output format can be changed with `--format` and written to a file with `-o`:

    tox config -e 3.13 --format json -o config.json
    tox config -e 3.13 --format toml -o config.toml

This is useful for debugging configuration issues and for programmatic consumption.

## Next steps

Now that you have a working tox setup, explore these topics:

- Concepts – understand how tox works (parallel mode, packaging, auto-provisioning)

- How-to Guides – practical recipes for common tasks (including testing across old and new Python versions with virtualenv_spec)

- Configuration – full configuration reference

- CLI interface – complete CLI reference

- Run a PEP 723 script – run standalone scripts with inline dependencies (PEP 723)