At PyConDE Berlin 2019 Florian Bruhin gave a really nice session about testing with pytest, which I try to recap here.
If You want to work with pytest you can install it via:
pip install pytest
When you know basic python unittest fixtures, good news ahead:
pytest is compatible and will run your old unittest classes as well, but pytest doesn’t need to have a testclass derived from some subclass.
It is sufficient to have a single python file which name starts with test_ containing a function which name also starts with test_
# test_stuff.py def test_stuff(): x = 5.0 assert x == 5
That’s all You need!
If you run pytest from the command line it will automatically discover tests which cohere to this naming convention like unittest -discover
Select test cases
You can specify the tests to be run by module::test_function or by module::test_class::test_method e.g.
If you pass
--durations=0 execution time for all tests will be reported.
Useful command line arguments
When learning pytest, it is good to learn some command line flags as well
- -h : help
- -x : quit on first error
- –pdb : start debugger on error
- -v : increase verbosity
- -s : show print output
- -rf : reason for failure
- -rs : reason for skipping
- -m <marker_name> : run only marked tests
- –fixtures : show fixtures in modules
Configuration via file
You can save your preferences for running pytest in a file called pytest.ini
[pytest] addopts = -x --durations=0 -vv
Fixtures are pytest’s equivalent to setUp methods from unittest with the difference that you can define when they should be used.
import pytest @pytest.fixture def some_value(): return 42 def test_function(some_value): assert some_value == 42
After declaring a fixture with decorator @pytest.fixture you can use this special function as a parameter to your test functions.
Without any further definition a fixture function is called before every function it is used in. When You do some heavy lifting in a fixture and you want to reuse that you can specify the module scope so that the fixture function just runs once per module
If you even want to instantiate a fixture once per session this is also possible with