How to speed up pytest

PythonPerformancePytest

Python Problem Overview


Is there some way to speed up the repeated execution of pytest? It seems to spend a lot of time collecting tests, even if I specify which files to execute on the command line. I know it isn't a disk speed issue either since running pyflakes across all the .py files is very fast.


The various answers represent different ways pytest can be slow. They helped sometimes, did not in others. I'm adding one more answer that explains a common speed problem. But it's not possible to select "The" answer here.

Python Solutions


Solution 1 - Python

Using the norecursedirs option in pytest.ini or tox.ini can save a lot of collection time, depending on what other files you have in your working directory. My collection time is roughly halved for a suite of 300 tests when I have that in place (0.34s vs 0.64s).

If you're already using tox like I am, you just need to add the following in your tox.ini:

[pytest]
norecursedirs = docs *.egg-info .git appdir .tox

You can also add it in a free-standing pytest.ini file.

The pytest documentation has more details on pytest configuration files.

Solution 2 - Python

I was having the same problem where I was calling pytest at the root of my project and my tests were three subdirectories down. The collection was taking 6-7 seconds before 0.4 seconds of actual test execution.

My solution initially was to call pytest with the relative path to the tests:

pytest src/www/tests/

If doing that speeds up your collection also, you can add the relative path to the tests to the end of the addopts setting in your pytest.ini - eg:

[pytest]
addopts = --doctest-glob='test_*.md' -x src/www/tests/

This dropped the collection + execution time down to about a second and I could still just call pytest as I was before.

Solution 3 - Python

With xdist you can parallelize pytest runs. It allows even to ship tests to remote machines. Depends on your setup it can speedup quite a bit :)

Solution 4 - Python

For me, adding PYTHONDONTWRITEBYTECODE=1 to my environment variables achieved a massive speedup! Note that I am using network drives which might be a factor.

  • Windows Batch: set PYTHONDONTWRITEBYTECODE=1
  • Unix: export PYTHONDONTWRITEBYTECODE=1
  • subprocess.run: Add keyword env={'PYTHONDONTWRITEBYTECODE': '1'}
  • PyCharm already set this variable automatically for me.

Note that the first two options only remain active for your current terminal session.

Solution 5 - Python

In the special case where you are running under cygwin's python, its unix-style file handling is slow. See pytest.py test very slow startup in cygwin for how to speed things up in that special situation.

Solution 6 - Python

If you have some antivirus software running, try turning it off. I had this exact same problem. Collecting tests ran incredibly slow. It turned out to be my antivirus software (Avast) that was causing the problem. When I disabled the antivirus software, test collection ran about five times faster. I tested it several times, turning the antivirus on and off, so I have no doubt that was the cause in my case.

Edit: To be clear, I don't think antivirus should be turned off and left off. I just recommend turning it off temporarily to see if it is the source of the slow down. In my case, it was, so I looked for other antivirus solutions that didn't have the same issue.

Solution 7 - Python

In bash, try { find -name '*_test.py'; find -name 'test_*.py'; } | xargs pytest.

For me, this brings total test time down to a fraction of a second.

Solution 8 - Python

Pytest imports all modules in the testpaths directories to look for tests. The import itself can be slow. This is the same startup time you'd experience if you ran those tests directly, however, since it imports all of the files it will be a lot longer. It's kind of a worst-case scenario.

This doesn't add time to the whole test run though, as it would need to import those files anyway to execute the tests.

If you narrow down the search on the command line, to specific files or directories, it will only import those ones. This can be a significant speedup while running specific tests.

Speeding up those imports involves modifying those modules. The size of the module, and the transitive imports, slow down the startup. Additionally look for any code that is executed -- code outside of a function. That also needs to be executed during the test collection phase.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionedA-qa mort-ora-yView Question on Stackoverflow
Solution 1 - PythonscannyView Answer on Stackoverflow
Solution 2 - PythonthisismyrobotView Answer on Stackoverflow
Solution 3 - PythonneutrinusView Answer on Stackoverflow
Solution 4 - PythonxjclView Answer on Stackoverflow
Solution 5 - PythonrockyView Answer on Stackoverflow
Solution 6 - PythonSeanView Answer on Stackoverflow
Solution 7 - PythonJashaView Answer on Stackoverflow
Solution 8 - PythonedA-qa mort-ora-yView Answer on Stackoverflow