Skip to content

Commit 8c7be91

Browse files
authored
Merge pull request #13846 from bluetech/native-toml
Add support for native TOML configuration
2 parents 9fc738c + 8ab2500 commit 8c7be91

40 files changed

+1831
-513
lines changed

changelog/13743.feature.rst

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
Added support for native TOML configuration files.
2+
3+
While pytest, since version 6, supports configuration in ``pyproject.toml`` files under ``[tool.pytest.ini_options]``,
4+
it does so in an "INI compatibility mode", where all configuration values are treated as strings or list of strings.
5+
Now, pytest supports the native TOML data model.
6+
7+
In ``pyproject.toml``, the native TOML configuration is under the ``[tool.pytest]`` table.
8+
9+
.. code-block:: toml
10+
11+
# pyproject.toml
12+
[tool.pytest]
13+
minversion = "9.0"
14+
addopts = ["-ra", "-q"]
15+
testpaths = [
16+
"tests",
17+
"integration",
18+
]
19+
20+
The ``[tool.pytest.ini_options]`` table remains supported, but both tables cannot be used at the same time.
21+
22+
If you prefer to use a separate configuration file, or don't use ``pyproject.toml``, you can use ``pytest.toml`` or ``.pytest.toml``:
23+
24+
.. code-block:: toml
25+
26+
# pytest.toml or .pytest.toml
27+
[pytest]
28+
minversion = "9.0"
29+
addopts = ["-ra", "-q"]
30+
testpaths = [
31+
"tests",
32+
"integration",
33+
]
34+
35+
The documentation now shows configuration snippets in both TOML and INI formats, in a tabbed interface.
36+
37+
See :ref:`config file formats` for full details.

changelog/13849.bugfix.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Hidden ``.pytest.ini`` files are now picked up as the config file even if empty.
2+
This was an inconsistency with non-hidden ``pytest.ini``.

doc/en/conf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"sphinx.ext.todo",
3535
"sphinx.ext.viewcode",
3636
"sphinx_removed_in",
37+
"sphinx_inline_tabs",
3738
"sphinxcontrib_trio",
3839
"sphinxcontrib.towncrier.ext", # provides `towncrier-draft-entries` directive
3940
"sphinx_issues", # implements `:issue:`, `:pr:` and other GH-related roles

doc/en/deprecations.rst

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -845,20 +845,38 @@ that manipulate this type of file (for example, Jenkins, Azure Pipelines, etc.).
845845
Users are recommended to try the new ``xunit2`` format and see if their tooling that consumes the JUnit
846846
XML file supports it.
847847

848-
To use the new format, update your ``pytest.ini``:
848+
To use the new format, update your configuration file:
849849

850-
.. code-block:: ini
850+
.. tab:: toml
851851

852-
[pytest]
853-
junit_family=xunit2
852+
.. code-block:: toml
853+
854+
[pytest]
855+
junit_family = "xunit2"
856+
857+
.. tab:: ini
858+
859+
.. code-block:: ini
860+
861+
[pytest]
862+
junit_family = xunit2
854863
855864
If you discover that your tooling does not support the new format, and want to keep using the
856865
legacy version, set the option to ``legacy`` instead:
857866

858-
.. code-block:: ini
867+
.. tab:: toml
868+
869+
.. code-block:: toml
870+
871+
[pytest]
872+
junit_family = "legacy"
873+
874+
.. tab:: ini
875+
876+
.. code-block:: ini
859877
860-
[pytest]
861-
junit_family=legacy
878+
[pytest]
879+
junit_family = legacy
862880
863881
By using ``legacy`` you will keep using the legacy/xunit1 format when upgrading to
864882
pytest 6.0, where the default format will be ``xunit2``.

doc/en/example/markers.rst

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -239,13 +239,21 @@ Registering markers
239239
240240
Registering markers for your test suite is simple:
241241

242-
.. code-block:: ini
242+
.. tab:: toml
243243

244-
# content of pytest.ini
245-
[pytest]
246-
markers =
247-
webtest: mark a test as a webtest.
248-
slow: mark test as slow.
244+
.. code-block:: toml
245+
246+
[pytest]
247+
markers = ["webtest: mark a test as a webtest.", "slow: mark test as slow."]
248+
249+
.. tab:: ini
250+
251+
.. code-block:: ini
252+
253+
[pytest]
254+
markers =
255+
webtest: mark a test as a webtest.
256+
slow: mark test as slow.
249257
250258
Multiple custom markers can be registered, by defining each one in its own line, as shown in above example.
251259

doc/en/example/pythoncollection.rst

Lines changed: 70 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,21 @@ Example:
8888
Changing directory recursion
8989
-----------------------------------------------------
9090

91-
You can set the :confval:`norecursedirs` option in an ini-file, for example your ``pytest.ini`` in the project root directory:
91+
You can set the :confval:`norecursedirs` option in a configuration file:
9292

93-
.. code-block:: ini
93+
.. tab:: toml
9494

95-
# content of pytest.ini
96-
[pytest]
97-
norecursedirs = .svn _build tmp*
95+
.. code-block:: toml
96+
97+
[pytest]
98+
norecursedirs = [".svn", "_build", "tmp*"]
99+
100+
.. tab:: ini
101+
102+
.. code-block:: ini
103+
104+
[pytest]
105+
norecursedirs = .svn _build tmp*
98106
99107
This would tell ``pytest`` to not recurse into typical subversion or sphinx-build directories or into any ``tmp`` prefixed directory.
100108

@@ -108,14 +116,25 @@ the :confval:`python_files`, :confval:`python_classes` and
108116
:confval:`python_functions` in your :ref:`configuration file <config file formats>`.
109117
Here is an example:
110118

111-
.. code-block:: ini
119+
.. tab:: toml
120+
121+
.. code-block:: toml
112122
113-
# content of pytest.ini
114-
# Example 1: have pytest look for "check" instead of "test"
115-
[pytest]
116-
python_files = check_*.py
117-
python_classes = Check
118-
python_functions = *_check
123+
# Example 1: have pytest look for "check" instead of "test"
124+
[pytest]
125+
python_files = ["check_*.py"]
126+
python_classes = ["Check"]
127+
python_functions = ["*_check"]
128+
129+
.. tab:: ini
130+
131+
.. code-block:: ini
132+
133+
# Example 1: have pytest look for "check" instead of "test"
134+
[pytest]
135+
python_files = check_*.py
136+
python_classes = Check
137+
python_functions = *_check
119138
120139
This would make ``pytest`` look for tests in files that match the ``check_*
121140
.py`` glob-pattern, ``Check`` prefixes in classes, and functions and methods
@@ -152,12 +171,21 @@ The test collection would look like this:
152171
153172
You can check for multiple glob patterns by adding a space between the patterns:
154173

155-
.. code-block:: ini
174+
.. tab:: toml
175+
176+
.. code-block:: toml
177+
178+
# Example 2: have pytest look for files with "test" and "example"
179+
[pytest]
180+
python_files = ["test_*.py", "example_*.py"]
156181
157-
# Example 2: have pytest look for files with "test" and "example"
158-
# content of pytest.ini
159-
[pytest]
160-
python_files = test_*.py example_*.py
182+
.. tab:: ini
183+
184+
.. code-block:: ini
185+
186+
# Example 2: have pytest look for files with "test" and "example"
187+
[pytest]
188+
python_files = test_*.py example_*.py
161189
162190
.. note::
163191

@@ -178,14 +206,22 @@ example if you have unittest2 installed you can type:
178206
pytest --pyargs unittest2.test.test_skipping -q
179207
180208
which would run the respective test module. Like with
181-
other options, through an ini-file and the :confval:`addopts` option you
209+
other options, through a configuration file and the :confval:`addopts` option you
182210
can make this change more permanently:
183211

184-
.. code-block:: ini
212+
.. tab:: toml
213+
214+
.. code-block:: toml
215+
216+
[pytest]
217+
addopts = ["--pyargs"]
218+
219+
.. tab:: ini
185220

186-
# content of pytest.ini
187-
[pytest]
188-
addopts = --pyargs
221+
.. code-block:: ini
222+
223+
[pytest]
224+
addopts = --pyargs
189225
190226
Now a simple invocation of ``pytest NAME`` will check
191227
if NAME exists as an importable package/module and otherwise
@@ -224,11 +260,19 @@ Customizing test collection
224260
225261
You can easily instruct ``pytest`` to discover tests from every Python file:
226262

227-
.. code-block:: ini
263+
.. tab:: toml
264+
265+
.. code-block:: toml
266+
267+
[pytest]
268+
python_files = ["*.py"]
269+
270+
.. tab:: ini
271+
272+
.. code-block:: ini
228273
229-
# content of pytest.ini
230-
[pytest]
231-
python_files = *.py
274+
[pytest]
275+
python_files = *.py
232276
233277
However, many projects will have a ``setup.py`` which they don't want to be
234278
imported. Moreover, there may files only importable by a specific python

doc/en/example/simple.rst

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,19 @@ every time you use ``pytest``. For example, if you always want to see
1111
detailed info on skipped and xfailed tests, as well as have terser "dot"
1212
progress output, you can write it into a configuration file:
1313

14-
.. code-block:: ini
14+
.. tab:: toml
1515

16-
# content of pytest.ini
17-
[pytest]
18-
addopts = -ra -q
16+
.. code-block:: toml
17+
18+
[pytest]
19+
addopts = ["-ra", "-q"]
20+
21+
.. tab:: ini
22+
23+
.. code-block:: ini
24+
25+
[pytest]
26+
addopts = -ra -q
1927
2028
2129
Alternatively, you can set a ``PYTEST_ADDOPTS`` environment variable to add command
@@ -29,7 +37,7 @@ Here's how the command-line is built in the presence of ``addopts`` or the envir
2937

3038
.. code-block:: text
3139
32-
<pytest.ini:addopts> $PYTEST_ADDOPTS <extra command-line arguments>
40+
<configuration file addopts> $PYTEST_ADDOPTS <extra command-line arguments>
3341
3442
So if the user executes in the command-line:
3543

doc/en/explanation/goodpractices.rst

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -94,14 +94,21 @@ This has the following benefits:
9494

9595
For new projects, we recommend to use ``importlib`` :ref:`import mode <import-modes>`
9696
(see which-import-mode_ for a detailed explanation).
97-
To this end, add the following to your ``pyproject.toml``:
97+
To this end, add the following to your configuration file:
9898

99-
.. code-block:: toml
99+
.. tab:: toml
100+
101+
.. code-block:: toml
102+
103+
[pytest]
104+
addopts = ["--import-mode=importlib"]
105+
106+
.. tab:: ini
107+
108+
.. code-block:: ini
100109
101-
[tool.pytest.ini_options]
102-
addopts = [
103-
"--import-mode=importlib",
104-
]
110+
[pytest]
111+
addopts = --import-mode=importlib
105112
106113
.. _src-layout:
107114

@@ -126,12 +133,21 @@ which are better explained in this excellent `blog post`_ by Ionel Cristian Măr
126133
PYTHONPATH=src pytest
127134
128135
or in a permanent manner by using the :confval:`pythonpath` configuration variable and adding the
129-
following to your ``pyproject.toml``:
136+
following to your configuration file:
130137

131-
.. code-block:: toml
138+
.. tab:: toml
139+
140+
.. code-block:: toml
141+
142+
[pytest]
143+
pythonpath = ["src"]
144+
145+
.. tab:: ini
146+
147+
.. code-block:: ini
132148
133-
[tool.pytest.ini_options]
134-
pythonpath = "src"
149+
[pytest]
150+
pythonpath = src
135151
136152
.. note::
137153

0 commit comments

Comments
 (0)