pytest-collect-profile
Find what makes pytest collection slow.
pytest-collect-profile shows which collector operations take the most time,
attributes their time to observed pytest hooks, and reports how long collection
takes overall. It measures pytest directly, including custom collectors, so the
report matches the suite pytest actually sees.
Installation
python -m pip install pytest-collect-profile
Quick start
Profile collection only — recommended
pytest --collect-profile-only
Start here when you want a diagnosis, not a test run. Pytest collects and selects the tests, the plugin prints one report, and the run stops. It does not print the usual list of collected nodes.
Only the 10 slowest collector operations are shown. Attribution is limited to the first 3 rows, with at most 3 named hooks per collector and 3 named collection-level hooks. The output stays useful in a terminal, a CI log, or coding-agent context even for large suites.
Profile collection, then run tests
pytest --collect-profile
Use this when you want to see the profile without changing your normal test run. The selected tests execute after the report is printed.
Need pytest's complete collected-node listing? Add --collect-only or --co to either command. An explicit pytest collect-only option keeps its native output.
Example report
====================== collect profile ======================
time collector node
1.421s Module tests/integration/test_api.py
0.612s Class tests/test_users.py::TestUsers
0.184s Directory tests/integration
collector attribution
1. Module tests/integration/test_api.py
direct fan-out: 842 children | 842 items
1.100s | 1 call | pytest_generate_tests
0.050s | 7 calls | pytest_pycollect_makeitem
0.020s | 842 calls | pytest_make_parametrize_id
0.010s | 4 calls | other observed hooks
0.100s | nested collectors
0.141s | outside observed hooks
2. Class tests/test_users.py::TestUsers
direct fan-out: 842 children | 842 items
0.200s | 1 call | pytest_generate_tests
0.100s | 7 calls | pytest_pycollect_makeitem
0.050s | 842 calls | pytest_make_parametrize_id
0.010s | 4 calls | other observed hooks
0.252s | outside observed hooks
3. Directory tests/integration
direct fan-out: 1 children | 0 items
0.020s | 3 calls | pytest_ignore_collect
0.010s | 2 calls | pytest_collect_file
0.154s | outside observed hooks
collection-level hooks
0.300s | 1 call | pytest_collection_modifyitems
0.020s | 4 calls | pytest_collectreport
0.010s | 842 calls | pytest_itemcollected
0.005s | 2 calls | other observed hooks
Total collection: 2.340s | 842 items
Reading the report
- The slowest collector operations appear first, with at most 10 rows.
- The first 3 rows receive attribution detail. Hook lines are ordered by raw
exclusive time, then by hook name; further hooks are folded into
other observed hookswith their time and call counts preserved. - A hook duration covers the complete hook call, excluding nested hook calls. It does not time or blame individual hook implementations or plugins.
direct fan-outcounts the collector's immediate children and immediate test items from its completed collection report. It is not a descendant total.nested collectorsis the inclusive time of directly nested collector operations and appears only when nonzero.outside observed hooksis the collector duration left after its observed exclusive hook time and direct nested collectors are subtracted. It is not a claim about imports, pytest internals, or custom collector code.- Hooks observed outside any active collector appear separately under
collection-level hooks, also with at most 3 named entries. Total collectionmeasures the complete collection phase separately.- Collector calls may be nested, so row times can overlap and are not meant to add up to the total.
- An empty root-session node ID is shown as
<session>.
The report points to where collection time is spent. It does not guess why a collector is slow or promise that changing one row will reduce the total by the same amount.
Works with pytest
- The plugin is silent unless one of its two profiling options is present.
- Pytest continues to own selection, diagnostics, warnings, and exit status.
-q,-qq, and-vkeep their normal pytest meaning.- Timings exist only for the current process. The plugin stores no history or cache and makes no network requests.
Compatibility
pytest-collect-profile requires Python 3.10 or newer and pytest 8.0 or newer. The project targets Linux, macOS, and Windows, with CI coverage across Python 3.10 through 3.14 and representative pytest 8.x and 9.x releases.
pytest-xdist
For a meaningful collection profile, run xdist projects serially:
pytest -n0 --collect-profile-only
The profile-only mode rejects active distributed execution and points to -n0. The regular --collect-profile mode does not aggregate worker results, so -n0 is recommended there as well.
Focused by design
pytest-collect-profile does one thing: profile collection. It does not profile test execution, fixtures, functions, or call stacks. It does not provide exports, history, run-to-run comparisons, thresholds, or configurable rankings and filters.
See the contribution guide for contribution guidance. This project is available under the terms of the MIT License.
Release files for pytest-collect-profile 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pytest_collect_profile-0.3.0.tar.gz | 17.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pytest_collect_profile-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 25.5 kB
Release files / pytest_collect_profile-0.3.0.tar.gz
| Download URL | pytest_collect_profile-0.3.0.tar.gz |
|---|---|
| Size | 17.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f61ea6970378d7a942dbd9a94d0ff573dd2adab3153669d7c4f06c60e0dd6ab7
|
|
BLAKE2b-256 checksum How to use checksums |
8b59585b2cd2490db769eb2eb64b58725fd61f9fa57346c676d2207015869b8b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 14, 2026.
Transparency logRelease files / pytest_collect_profile-0.3.0-py3-none-any.whl
| Download URL | pytest_collect_profile-0.3.0-py3-none-any.whl |
|---|---|
| Size | 8.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b0c3f44f9a6908f3300426d528afef9f315aa2961be1914feef7dee8236ac2a4
|
|
BLAKE2b-256 checksum How to use checksums |
f929448f1c5778be64d43d5f7bf09065b2ae6e46f1939b732ac518c9c8a0cba2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 14, 2026.
Transparency log