Can I run line_profiler over a pytest test?

后端 未结 3 1798
挽巷
挽巷 2021-02-03 21:28

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

相关标签:
3条回答
  • 2021-02-03 21:48

    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.

    0 讨论(0)
  • 2021-02-03 21:49

    Have you tried the pytest-profiling plugin?

    0 讨论(0)
  • 2021-02-03 21:56

    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.

    0 讨论(0)
提交回复
热议问题