How to build a tox multi-env matrix with mock config in Python

Simulate a tox multi-environment matrix by validating environment names and grouping extras into a readable matrix structure.

Easy Python 3.9+ Aug 9, 2026 Modern tooling 13 views 0 copies

Requires third-party packages — install first
pip install tox

Python code

37 lines
Python 3.9+
```python
import tox

def run_tox_matrix(mock_envs):
    """Simulate a tox multi-env configuration and verify mock choices."""
    config = {
        "tox": {
            "envlist": mock_envs,
            "config": {
                "basepython": "python3.9",
                "deps": ["pytest", "mock"],
            },
        }
    }
    
    # Inspect the mock environment list to ensure it follows expected matrix rules
    validated_envs = []
    for env in config["tox"]["envlist"]:
        if env in ("py39", "py310"):
            validated_envs.append((env, "default"))
        elif env.startswith("py39-"):
            py_version, extra = env.split("-", 1)
            validated_envs.append((py_version, extra))
        else:
            raise ValueError(f"Unexpected env: {env}")
    
    # Build a mock matrix representation
    matrix = {}
    for env, extra in validated_envs:
        matrix.setdefault(env, []).append(extra)
        print(f"Env: {env}, extra: {extra}")
    
    print(f"Matrix summary: {matrix}")
    return matrix

if __name__ == "__main__":
    run_tox_matrix(["py39", "py310", "py39-django", "py39-flask"])

Output

stdout
Env: py39, extra: default
Env: py310, extra: default
Env: py39, extra: django
Env: py39, extra: flask
Matrix summary: {'py39': ['default', 'django', 'flask'], 'py310': ['default']}

How it works

This code models a tox configuration as a dictionary, mimicking how tox defines multiple environments with an envlist. It validates each environment name against expected patterns (like py39 or py310) and splits compound names using a hyphen to extract the Python version and an extra flavor such as 'django' or 'flask'. The matrix groups extras per Python version, which mirrors how tox expands matrix combos into discrete environments. Printing the summary gives a quick audit of what tox would run. This pattern is useful for writing config generation tools or validating CI matrix definitions before execution.

Common mistakes

  • Forgetting that tox env names are case-sensitive and platform-dependent
  • Splitting env names without checking the separator exists first
  • Assuming the matrix output order matches the original envlist order when using setdefault on dicts

Variations

  1. Use tox's built-in config parsing with tox.config.parseconfig to read an actual tox.ini file.
  2. Leverage itertools.product to generate the full matrix from separate version and extra lists instead of iterating a flat envlist.

Real-world use cases

  • Generating CI job matrices from a tox envlist to trigger parallel builds for each Python version and dependency combo.
  • Validating tox.ini env names before a release pipeline to catch typos and unsupported platform suffixes.
  • Building a dashboard that aggregates test results across the tox matrix by parsing env names and grouping them.

Sponsored

Run locally

This sample needs third-party packages, so it cannot run in the browser IDE. Copy the code above, install the packages shown at the top, then run it in your own Python environment.

More from Modern tooling

Related tutorials and quizzes for this topic.