@@ -18,8 +18,9 @@ to test with different dependency configurations and different configurations
1818for different operating systems. tox uses project information from the
1919:file: `setup.py ` or :file: `pyproject.toml ` file for the package under test to
2020create an installable :doc: `distribution of your package
21- <../packs/distribution>`. It searches the :file: `tox.ini ` file for a list of
22- environments and then performs the following steps for each:
21+ <../packs/distribution>`. It searches for a list of environments in the
22+ ``[tool.tox] `` section of the :file: `pyproject.toml ` file, and then performs the
23+ following steps for each one:
2324
2425#. creates a :term: `virtual environment <Virtual environment> `
2526#. installs some dependencies with :term: `pip `
@@ -35,54 +36,30 @@ To accelerate this process with :term:`uv`, we don’t use tox directly, but
3536Setting up tox
3637--------------
3738
38- Until now, we had the items code in a :file: `src/ ` directory and the tests in
39- :file: `tests/api/ ` and :file: `tests/cli/ `. Now we will add a :file: `tox.ini `
40- file so that the structure looks like this:
39+ Previously, tox was usually configured in the :file: `tox.ini ` file. However,
40+ since tox 4.44.0, its functionality has been frozen and future configuration
41+ parameters will probably only be provided in a
42+ :doc: `Python4DataScience:data-processing/serialisation-formats/toml/index ` file,
43+ for example in the :ref: `pyproject-toml ` file. Let’s take a look at a simple
44+ configuration in the :file: `pyproject.toml ` file:
4145
42- .. code-block :: console
43- :emphasize-lines: 16
44-
45- items
46- ├── …
47- ├── pyproject.toml
48- ├── src
49- │ └── items
50- │ └── …
51- ├── tests
52- │ ├── api
53- │ │ ├── __init__.py
54- │ │ ├── conftest.py
55- │ │ └── test_….py
56- │ └── cli
57- │ ├── __init__.py
58- │ ├── conftest.py
59- │ └── test_….py
60- └── tox.ini
61-
62- This is a typical layout for many projects. Let’s take a look at a simple
63- :file: `tox.ini ` file in the Items project:
64-
65- .. code-block :: ini
66-
67- [tox]
68- envlist = py313
69-
70- [testenv]
71- deps =
72- pytest>=6.0
73- faker
74- commands = pytest
75-
76- In the ``[tox] `` section, we have defined ``envlist = py313 ``. This is a
77- shortcut that tells tox to run our tests with Python version 3.13. We will be
78- adding more Python versions shortly, but using one version helps to understand
79- the flow of tox.
80-
81- In the ``[testenv] `` section, ``pytest `` and ``faker `` are listed as
82- dependencies under ``deps ``. So tox knows that we need these two tools for
83- testing. If you wish, you can also specify which version should be used, for
84- example ``pytest>=6.0 ``. Finally, commands instruct tox to execute ``pytest `` in
85- every environment.
46+ .. code-block :: toml
47+
48+ [tool.tox]
49+ env_list = ["py313"]
50+
51+ [tool.tox.env_run_base]
52+ dependency_groups = [ "tests" ]
53+ commands = [[ "pytest"]]
54+
55+ In the ``[tool.tox] `` section, we defined ``env_list = ["py313"] ``. This is a
56+ shorthand that instructs tox to run our tests using Python version 3.13. We will
57+ add more Python versions shortly, but using one version helps us better
58+ understand how tox works.
59+
60+ In the ``[tool.tox.env_run_base] `` section, ``dependency_groups `` specifies
61+ ``tests ``. This tells tox that the corresponding libraries should be installed
62+ in this environment. Finally, ``commands `` instructs tox to run ``pytest ``.
8663
8764Executing tox
8865-------------
@@ -156,21 +133,22 @@ To run tox, simply start tox:
156133 Testing multiple Python versions
157134--------------------------------
158135
159- To do this, we extend ``envlist `` in the :file: `tox.ini ` file to add further
160- Python versions:
136+ To do this, we extend ``envlist `` in the :file: `pyproject.toml ` file to add
137+ further Python versions:
161138
162- .. code-block :: ini
139+ .. code-block :: toml
163140
164- [tox]
165- envlist =
166- py3{10-14}
167- py3{13-14}t
168- skip_missing_interpreters = True
141+ [tool.tox]
142+ env_list = [
143+ "py3{10-14}",
144+ "py{13-14}t",
145+ ]
146+ skip_missing_interpreters = true
169147
170148 We will now test Python versions from 3.10 to 3.14. In addition, we have also
171- added the setting ``skip_missing_interpreters = True `` so that tox does not fail
149+ added the setting ``skip_missing_interpreters = true `` so that tox does not fail
172150if one of the listed Python versions is missing on your system. If the value is
173- set to ``True ``, tox will run the tests with every available Python version, but
151+ set to ``true ``, tox will run the tests with every available Python version, but
174152will skip versions it doesn’t find without failing. The output is very similar,
175153although I will only highlight the differences in the following illustration:
176154
@@ -248,10 +226,10 @@ although I will only highlight the differences in the following illustration:
248226 Before tox 4.25.0 dated 27 March 2025, the versions had to be specified one
249227 by one:
250228
251- .. code-block :: ini
229+ .. code-block :: toml
252230
253- [tox]
254- envlist = py3{10,11,12,13,14,13t,14t}
231+ [tool. tox]
232+ envlist = [ py3{10,11,12,13,14,13t,14t}]
255233
256234 Running Tox environments in parallel
257235------------------------------------
@@ -284,35 +262,44 @@ other. It is also possible to run them in parallel with the ``-p`` option:
284262Add coverage report in tox
285263--------------------------
286264
287- The configuration of coverage reports can easily be added to the :file: `tox.ini `
288- file. To do this, we need to add ``pytest-cov `` to the ``deps `` settings so that
289- the ``pytest-cov `` plugin is installed in the tox test environments. Including
290- ``pytest-cov `` also includes all its dependencies, such as ``coverage ``. We then
291- extend commands to ``pytest --cov=items ``:
292-
293- .. code-block ::
294- :emphasize-lines: 11-
295-
296- [tox]
297- envlist =
298- py3{10-14}
299- py3{13-14}t
300- skip_missing_interpreters = True
301-
302- [testenv]
303- deps =
304- pytest>=6.0
305- faker
306- commands = pytest
307-
308- [testenv:coverage-report]
309- description = Report coverage over all test runs.
310- deps = coverage[toml]
311- skip_install = true
312- allowlist_externals = coverage
313- commands =
314- coverage combine
315- coverage report
265+ The configuration of coverage reports can easily be added to the
266+ :file: `pyproject.toml ` file. To do this, we need to add ``pytest-cov `` to the
267+ ``tests `` dependency group so that the ``pytest-cov `` plugin is also installed
268+ in the tox test environments. Including ``pytest-cov `` also includes all other
269+ dependencies, such as ``coverage ``. We then add
270+ :samp: `env.coverage-report.{ OPTIONS } ` and change ``env_run_base.commands ``:
271+
272+ .. code-block :: toml
273+ :emphasize-lines: 6, 16-23, 26-
274+
275+ [dependency-groups]
276+ ...
277+ tests = [
278+ "faker",
279+ "pytest>=6",
280+ "pytest-cov",
281+ ]
282+
283+ [tool.tox]
284+ requires = [ "tox>=4" ]
285+ env_list = [
286+ "py3{10-14}",
287+ "py{13-14}t",
288+ ]
289+ skip_missing_interpreters = true
290+ env.coverage-report.description = "Report coverage over all test runs."
291+ env.coverage-report.deps = [ "coverage[toml]" ]
292+ env.coverage-report.depends = [ "py" ]
293+ env.coverage-report.skip_install = true
294+ env.coverage-report.commands = [
295+ [ "coverage combine" ],
296+ [ "coverage report" ],
297+ ]
298+ env_run_base.dependency_groups = [ "tests" ]
299+ env_run_base.deps = [ "coverage[toml]" ]
300+ env_run_base.commands = [
301+ [ "coverage", "run", "-m", "pytest" ],
302+ ]
316303
317304 When using Coverage with ``tox ``, it can sometimes be useful to add a section in
318305the :file: `pyproject.toml ` file to tell Coverage which source code paths should
@@ -377,25 +364,25 @@ Passing pytest parameters to tox
377364We can also call individual tests with tox by making another change so that
378365:term: `parameters <Parameter> ` can be passed to pytest:
379366
380- .. code-block :: ini
381- :emphasize-lines: 15-
382-
383- [tox]
384- envlist =
385- pre-commit
386- docs
387- py3{10-14}
388- py3{13 -14}t
389- coverage-report
390- skip_missing_interpreters = True
391-
392- [testenv]
393- dependency_groups = tests
394- deps =
395- tests: coverage[toml]
396- allowlist_externals = coverage
397- commands =
398- coverage run -m pytest {posargs}
367+ .. code-block :: toml
368+ :emphasize-lines: 15
369+
370+ [tool. tox]
371+ requires = [ "tox>=4" ]
372+ env_list = [
373+ "pre-commit",
374+ "docs",
375+ " py3{10 -14}",
376+ "py{13-14}t",
377+ "coverage-report",
378+ ]
379+ skip_missing_interpreters = true
380+ env_run_base. dependency_groups = [ " tests" ]
381+ env_run_base. deps = [ "coverage[toml]" ]
382+ env_run_base.commands = [
383+ [ "python", "--version", "--version" ],
384+ [ "coverage", "run", "-m", "pytest", "{posargs}" ],
385+ ]
399386
400387 To pass arguments to pytest, insert them between the tox arguments and the
401388pytest arguments. In this case, we select ``test_version `` tests with the ``-k ``
@@ -455,16 +442,16 @@ of environments are available for GitHub actions:
455442 if : always()
456443
457444 steps :
458- - uses : actions/checkout@v4
445+ - uses : actions/checkout@v6
459446 with :
460447 persist-credentials : false
461- - uses : actions/setup-python@v5
448+ - uses : actions/setup-python@v6
462449 with :
463450 python-version-file : .python-version
464451 - uses : hynek/setup-cached-uv@v2
465452
466453 - name : Download coverage data
467- uses : actions/download-artifact@v4
454+ uses : actions/download-artifact@v7
468455 with :
469456 pattern : coverage-data-*
470457 merge-multiple : true
@@ -603,18 +590,21 @@ You can install ``tox`` and ``tox-uv`` with:
603590 ``uv.lock `` support
604591~~~~~~~~~~~~~~~~~~~
605592
606- If you want to use ``uv sync `` with a ``uv.lock `` file for a Tox environment,
607- you must change the runner for this Tox environment to ``uv-venv-lock-runner ``.
608- You should also use the dependency_groups configuration in such environments
609- to instruct ``uv `` to install the specified dependency group, for example:
593+ If you want to use ``uv sync `` with a :file: `uv.lock ` file for a Tox
594+ environment, you must change the runner for this Tox environment to
595+ ``uv-venv-lock-runner ``, for example:
610596
611- .. code-block :: ini
612- :caption: tox.ini
597+ .. code-block :: toml
598+ :caption: pyproject.toml
599+
600+ env.app.dependency_groups = [ "tests" ]
601+ env.app.runner = "uv-venv-lock-runner"
602+ commands = [[ "pytest"]]
613603
614- [testenv]
615- runner = uv-venv-lock-runner
616- dependency_groups = dev
617- commands = pytest
604+ The ``app `` environment uses the ``uv-venv-lock-runner `` and utilises ``uv sync
605+ --locked `` to install the dependencies in the versions specified in the
606+ :file: `uv.lock ` file.
618607
619- ``dev `` uses the ``uv-venv-lock-runner `` and uses ``uv sync `` to install
620- dependencies in the environment with the ``dev `` dependency group.
608+ .. seealso ::
609+ * `uv.lock support
610+ <https://github.com/tox-dev/tox-uv?tab=readme-ov-file#uvlock-support> `_
0 commit comments