
Pytest — How to speed up your tests
This post will cover several techniques that you can use to speed up your pytest suite to hopefully make your test times a little more bearable.
Two of the approaches below are aimed at fixing slow tests which shouldn’t be slow and the other two focus on speeding up genuinely slow test suites.
1. Correct Fixture Scope
I’ve already written a comprehensive post on fixture scope usage, breaking down how it can easily inflate your test durations when not used correctly. You can check it out here.
2. Parallelisation
Traditionally, pytest suites operate sequentially, running each test one by one. This is fine for small or fast test suites but can become tedious for larger, more complex projects. An easy way to address this is through the use of the pytest-xdist plugin, which allows you to parallelise your tests, by distributing them across multiple CPUs.
pip install pytest-xdist pytest -n auto
Once installed, add -n auto to your existing pytest command to automatically spawn multiple workers equal to the number of available CPUs.
# With pytest-xdist
460 passed, 7 skipped, 224 warnings, 25 subtests passed in 68.64s (0:01:08)
# Running normally
460 passed, 7 skipped, 26 warnings, 25 subtests passed in 216.57s (0:03:36)3. Profiling
Are there a couple of tests that are responsible for the majority of your test time? You can’t fix a problem if you don’t know where it is or even worse, you didn’t know there was one in the first place. Rather than accepting slow tests, profile them regularly to see if there’s anything that stands out. This is trivial to do in pytest.
pytest --durations 10
The argument --durations 10 will run your tests as normal but then print out the slowest 10 tests for you to inspect further. It shows whether it was the test setup or the test itself that took a long time to execute. The value 10 can be replaced with whatever number of tests you would like to display.
slowest 10 durations 20.57s setup a/test_foo.py 8.69s call b/test_foo.py 8.64s call a/test_foo.py 7.09s setup a/test_foo.py 7.03s setup b/test_foo.py 5.63s setup a/test_foo.py 5.36s call b/test_foo.py 5.33s call a/test_foo.py 5.27s call b/test_foo.py 5.26s call b/test_foo.py
Some tests will genuinely need to take a long time, whether the setup is cumbersome or it's doing some heavy processing. Any unexpected slow tests identified will either be doing some silly that can be fixed immediately or will need further, individual profiling. For this, I would recommend pytest-profiling or the cProfile functionality bundled with the Python standard library.
4. Skip Slow
If some legitimately slow tests are fairly stable and not likely to change or fail, they can be skipped during local development and then re-enabled when necessary. This would usually beat a certain stage of your CI pipeline if you have one. This can remove friction from your local development workflow while still keeping the layer of assurance of all tests passing before any code is merged.
This can easily be achieved through the use of the pytest-skip-slow extension. Once installed, you can mark specific slow tests with the @pytest.mark.slow decorator, which will cause them to be skipped on normal test runs, saving time. When you want to run the full test suite, including the slow ones, simply pass the --slow argument to pytest.
pytest --slow
Summary
Hopefully, the suggestions above can help improve or speed up your test suites. For a full breakdown of all the other checks you can do to speed up your tests, check out the repository below, which I found incredibly useful.






