Pytest Profiling Plugin
pytest-profiling is a plugin for the pytest testing framework that provides code profiling capabilities. It generates profiling information in tabular format and can also produce call-graph heat maps in SVG format. The plugin uses Python's built-in `cProfile` module for profiling and `pstats` for analysis, with `gprof2dot` and `dot` (Graphviz) for SVG visualization. It is actively maintained, with regular updates to support recent Python and pytest versions, as seen by its latest releases (v1.8.1 in November 2024 and v1.8.0 in October 2024).
Warnings
- breaking Version 1.8.0 and later dropped support for Python 2 and Python versions less than 3.6. Ensure your environment is running Python 3.6 or newer.
- gotcha Generating SVG profile graphs with `--profile-svg` requires external tools: `gprof2dot` (Python package) and the `dot` command-line utility from Graphviz. These must be installed separately from `pytest-profiling`.
- gotcha By default, `pytest-profiling` might not extensively profile the setup/teardown phases of pytest fixtures, focusing primarily on the test function execution itself. This can lead to incomplete profiling results if significant time is spent within fixtures.
- gotcha The raw profiling output can be very verbose, often showing many internal `pytest` and library calls. Analyzing specific bottlenecks in your application code may require filtering the `pstats` output programmatically.
Install
-
pip install pytest-profiling
Imports
- pytest_plugins
pytest_plugins = ['pytest_profiling'] # in conftest.py
Quickstart
import pytest
def test_slow_function():
total = 0
for i in range(100000):
total += i * i
assert total > 0
# Run from command line:
# pytest --profile
# pytest --profile-svg
# Example of running the command:
# import subprocess
# import os
#
# # Create a dummy test file
# test_file_content = """
# import time
# def test_example_profile():
# time.sleep(0.01) # Simulate some work
# x = 0
# for i in range(1000):
# x += i
# assert x == 499500
# """
# with open("test_example_profile.py", "w") as f:
# f.write(test_file_content)
#
# print("\n--- Running pytest --profile ---")
# profile_cmd = ["pytest", "--profile", "test_example_profile.py"]
# result = subprocess.run(profile_cmd, capture_output=True, text=True, check=False)
# print(result.stdout)
# if result.stderr: print(result.stderr)
#
# # Optional: Clean up
# # os.remove("test_example_profile.py")
# # import shutil
# # if os.path.exists("prof"): shutil.rmtree("prof")