Skip to content

Commit fbaae93

Browse files
committed
📝 Switch to pyproject.toml for tox config
1 parent 2414bf7 commit fbaae93

File tree

1 file changed

+115
-125
lines changed

1 file changed

+115
-125
lines changed

docs/test/tox.rst

Lines changed: 115 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ to test with different dependency configurations and different configurations
1818
for different operating systems. tox uses project information from the
1919
:file:`setup.py` or :file:`pyproject.toml` file for the package under test to
2020
create 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
3536
Setting 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

8764
Executing 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
172150
if 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
174152
will skip versions it doesn’t find without failing. The output is very similar,
175153
although 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:
284262
Add 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
318305
the :file:`pyproject.toml` file to tell Coverage which source code paths should
@@ -377,25 +364,25 @@ Passing pytest parameters to tox
377364
We 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
401388
pytest 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

Comments
 (0)