Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I run line_profiler over a pytest test?

I have identified some long running pytest tests with

py.test --durations=10 

I would like to instrument one of those tests now with something like line_profiler or cprofile. I really want to get the profile data from the test itself as the pytest setup or tear down could well be part of what is slow.

However given how line_profiler or cprofile is typically involved it isn't clear to me how to make them work with pytest.

like image 763
Atlas1j Avatar asked Sep 16 '13 14:09

Atlas1j


People also ask

How do I run multiple pytest files?

Run Multiple Tests From a Specific File and Multiple Files To run all the tests from all the files in the folder and subfolders we need to just run the pytest command. This will run all the filenames starting with test_ and the filenames ending with _test in that folder and subfolders under that folder.

How do I run a test file in pytest?

Try this: py. test test_basic.py -k test_first here test_first is a test case present in my test_basic.py file. Use the :: syntax to run a single test in a test file, e.g.: pytest tests/test_models.py::TestMyModel . TestMyModel is a class that contains a subset of tests.

How does pytest know what tests to run?

Pytest supports several ways to run and select tests from the command-line. This will run tests which contain names that match the given string expression (case-insensitive), which can include Python operators that use filenames, class names and function names as variables.

How do I skip Testcases in pytest?

The simplest way to skip a test is to mark it with the skip decorator which may be passed an optional reason . It is also possible to skip imperatively during test execution or setup by calling the pytest. skip(reason) function. This is useful when it is not possible to evaluate the skip condition during import time.


2 Answers

Run pytest like this:

python3 -m cProfile -o profile -m pytest 

You can even pass in optional arguments:

python3 -m cProfile -o profile -m pytest tests/worker/test_tasks.py -s campaigns 

This will create a binary file called profile in your current directory. This can be analyzed with pstats:

import pstats p = pstats.Stats('profile') p.strip_dirs() p.sort_stats('cumtime') p.print_stats(50) 

This will print the 50 lines with the longest cumulative duration.

like image 152
Danilo Bargen Avatar answered Sep 20 '22 06:09

Danilo Bargen


To get cProfile and line_profiler to work with py.test code, I did two things:

  1. Extended the py.test test code with a call to pytest.main(), which made it executable with the python interpreter as the main driver:

    # pytest_test.py: @profile # for line_profiler only def test_example():     x = 3**32     assert x == 1853020188851841  # for profiling with cProfile and line_profiler import pytest pytest.main(__file__) 

    Now you can run this test without py.test as the main driver using other tools:

    $ kernprof.py -l pytest_test.py $ python -m line_profiler pytest_test.py.lprof 

    or

    $ python -m cProfile pytest_test.py 
  2. To profile py.test-specific functions such as pytest_funcarg*() with line_profiler I split them in two to avoid confusion between py.test and line_profiler:

    def pytest_funcarg__foo(request):     return foo(request)  @profile def foo(request): ... 

The same method works for memory_profiler.

like image 44
Andrei Terechko Avatar answered Sep 22 '22 06:09

Andrei Terechko