Configuration¶
You can use configuration files to change the way pytest runs. If you repeatedly
use certain options in your tests, such as --verbose
or
--strict-markers
, you can store them in a configuration file so that you
don’t have to enter them again and again. In addition to the configuration
files, there are a handful of other files that are helpful when using pytest to
make writing and running tests easier:
pytest.ini
This is the most important configuration file of pytest, with which you can change the default behaviour of pytest. It also defines the root directory of pytest, or
rootdir
.conftest.py
This file contains Test fixtures and hook functions. It can exist in
rootdir
or in any subdirectory.__init__.py
If this file is stored in test subdirectories, it enables the use of identical test file names in several test directories.
If you already have a tox.ini
, pyproject.toml
or
setup.cfg
in your project, they can take the place of the
pytest.ini
file: tox.ini
is used by tox,
pyproject.toml
and setup.cfg
are used for packaging Python
projects and can be used to store settings for various tools, including pytest.
You should have a configuration file, either pytest.ini
, or a pytest
section in tox.ini
, pyproject.toml
or in setup.cfg
.
The configuration file defines the top-level directory from which pytest
is
started.
Let’s take a look at some of these files in the context of a project directory structure:
items
├── …
├── pytest.ini
├── src
│ └── …
└── tests
├── __init__.py
├── conftest.py
└── test_….py
In the case of the items
project that we have used for testing so far, there
is a pytest.ini
file and a tests
directory at the top level. We
will refer to this structure when we talk about the various files in the rest of
this section.
Saving settings and options in pytest.ini
¶
[pytest]
addopts =
--strict-markers
--strict-config
-ra
testpaths = tests
markers =
smoke: Small subset of all tests
exception: Only run expected exceptions
[pytest]
marks the start of the pytest section. This is followed by the
individual settings. For configuration settings that allow more than one value,
the values can be written either in one or more lines in the form
SETTING = VALUE1 VALUE2
. With markers
, however, only one
marker per line is permitted.
This example is a simple pytest.ini
file that I use in almost all my
projects. Let’s briefly go through the individual lines:
addopts =
allows you to specify the pytest options that we always want to execute in this project.
--strict-markers
instructs pytest to issue an error instead of a warning for every unregistered marker that appears in the test code. This allows us to avoid typos in marker names.
--strict-config
instructs pytest to issue an error instead of a warning if difficulties arise when parsing configuration files. This prevents typing errors in the configuration file from going unnoticed.
-ra
instructs pytest to display not only additional information on failures and errors at the end of a test run, but also a test summary.
-r
displays additional information on the test summary.
a
displays all but the passed tests. This adds the information
skipped
,xfailed
orxpassed
to the failures and errors.
testpaths = tests
tells pytest where to look for tests if you have not specified a file or directory name on the command line. In our case, pytest searches in the
tests
directory.At first glance, it may seem superfluous to set
testpaths
totests
, as pytest searches there anyway and we do not have anytest_
files in oursrc
ordocs
directories. However, specifying atestpaths
directory can save a little startup time, especially if oursrc
,docs
or other directories are quite large.markers =
is used to declare markers, as described in Selection of tests with your own markers.
See also
You can specify many other configuration settings and command line options in
the configuration files, which you can display using the pytest --help
command.
Using other configuration files¶
If you are writing tests for a project that already has a
pyproject.toml
, tox.ini
or setup.cfg
file, you can use
pytest.ini
to store your pytest configuration settings, or you can store
your configuration settings in one of these alternative configuration files. The
syntax of the two non-ini files is slightly different, so we will take a closer
look at both files.
pyproject.toml
¶
The pyproject.toml
file was originally intended for the packaging of
Python projects; however, it can also be used to define project settings.
As TOML is
a different standard for configuration files than .ini
files, the format
is also slightly different:
[tool.pytest.ini_options]
addopts = [
"--strict-markers",
"--strict-config",
"-ra"
]
testpaths = "tests"
markers = [
"exception: Only run expected exceptions",
"finish: Only run finish tests",
"smoke: Small subset of all tests",
"num_items: Number of items to be pre-filled for the items_db fixture"
]
Instead of [pytest]
, the section begins with [tool.pytest.ini_options]
,
the values must be enclosed in quotes and lists of values must be lists of
character strings in square brackets.
setup.cfg
¶
The file format of the setup.cfg
corresponds to an .ini
file:
[tool:pytest]
addopts =
--strict-markers
--strict-config
-ra
testpaths = tests
markers =
smoke: Small subset of all tests
exception: Only run expected exceptions
The only difference between this and pytest.ini
is the specification of
the [tool:pytest]
section.
Warning
However, the parser of the .cfg
file differs from the parser of the
.ini
file, and this difference can cause problems that are difficult
to track down, see also pytest documentation.
Set rootdir
¶
Before pytest searches for test files to execute, it reads the configuration
file pytest.ini
, tox.ini
, pyproject.toml
or
setup.cfg
, which contains a pytest section:
if you have specified a
test
directory, pytest will start searching thereif you have specified several files or directories, pytest starts with the parent directory
if you do not specify a file or directory, pytest starts in the current directory.
If pytest finds a configuration file in the start directory, this is the root
and if not, pytest goes up the directory tree until it finds a configuration
file that contains a pytest section. Once pytest has found a configuration file,
it marks the directory in which it found it as rootdir
. This root directory
is also the relative root of the IDs. pytest also tells you where it has found a
configuration file. Using these rules, we can run tests at different levels and
be sure that pytest finds the correct configuration file:
$ cd items
$ pytest
============================= test session starts ==============================
...
rootdir: /Users/veit/cusy/prj/items
configfile: pyproject.toml
testpaths: tests
plugins: Faker-19.11.0
collected 39 items
...
conftest.py
for sharing local fixtures and hook functions¶
The conftest.py
file is used to store fixtures and hook functions, see
also Test fixtures and Plugins. You can have as many
conftest.py
files in a project as you like. Everything that is defined
in a conftest.py
file applies to tests in this directory and all
subdirectories. If you have a conftest.py
file at the top test level,
the fixtures defined there can be used for all tests. If there are special
fixtures that only apply to a subdirectory, these can be defined in another
conftest.py file in this subdirectory. For example, the CLI tests may require
different fixtures than the API tests, and you can also share some of them.
Tip
However, it is a good idea to keep only one conftest.py
file so that
you can easily find the fixture definitions. Even though we can always find
out where a fixture is defined with pytest --fixtures -v
, it is still
easier if it is always defined in the one conftest.py
file.
__init__.py
to avoid collision of test file names¶
The __init__.py
file allows you to have duplicate test filenames. If you
have __init__.py
files in each test subdirectory, you can use the same
test filename in multiple directories, for example:
items
├── …
├── pytest.ini
├── src
│ └── …
└── tests
├── api
│ ├── __init__.py
│ └── test_add.py
├── cli
│ ├── __init__.py
│ ├── conftest.py
│ └── test_add.py
└── conftest.py
Now we can test the add
functionality both via the API and via the CLI,
whereby a test_add.py
is located in both directories:
$ pytest
============================= test session starts ==============================
...
rootdir: /Users/veit/cusy/prj/items
configfile: pyproject.toml
testpaths: tests
plugins: Faker-19.11.0
collected 6 items
tests/api/test_add.py .... [ 66%]
tests/cli/test_add.py .. [100%]
============================== 6 passed in 0.03s ===============================
Most of my projects start with the following configuration:
addopts =
--strict-markers
--strict-config
-ra
See also