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.iniThis 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.pyThis file contains Test fixtures and hook functions. It can exist in
rootdiror in any subdirectory.__init__.pyIf 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-markersinstructs 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-configinstructs 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.
-rainstructs pytest to display not only additional information on failures and errors at the end of a test run, but also a test summary.
-rdisplays additional information on the test summary.
adisplays all but the passed tests. This adds the information
skipped,xfailedorxpassedto the failures and errors.
testpaths = teststells 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
testsdirectory.At first glance, it may seem superfluous to set
testpathstotests, as pytest searches there anyway and we do not have anytest_files in oursrcordocsdirectories. However, specifying atestpathsdirectory can save a little startup time, especially if oursrc,docsor 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
testdirectory, 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