Библиотека coverage.py используется почти во всех проектах, где я работал, и де-факто стала стандартом для отчетов о покрытии тестами. Но я ни разу не видел, чтобы ее работу оптимизировали.
У coverage.py три ядра измерения:
ctrace (C-реализация sys.settrace), pytrace (то же на чистом Python) и sysmon (на базе sys.monitoring, PEP 669, Python 3.12+). Ядро выбирается переменной COVERAGE_CORE или, начиная с coverage 7.9, настройкой [run] core.Нас интересует sysmon. Разберем, почему он быстрее и когда его включать.
settrace вызывает trace-функцию на каждое выполнение каждой строки, хотя для покрытия достаточно знать, выполнялась ли строка хоть раз. sys.monitoring позволяет отключить событие после первого срабатывания, и дальше этот код работает без накладных расходов. По оценке автора coverage.py, для line coverage оверхед часто ниже 5%.Пример из практики: Trail of Bits на тестах PyPI (Python 3.12, поверх `pytest-xdist`) ускорили прогон с 58 до 27 секунд. Замер сделан в 2024 году. На актуальных версиях coverage в конфигурации "3.12 + branch coverage" такого эффекта уже не будет, почему - ниже.
Но есть нюансы:
• На 3.12/3.13 sysmon не работает с branch coverage: при
branch = true coverage выдает предупреждение и измеряет через ctrace, ускорения нет. На 3.14+ sysmon умеет измерять и ветки, так что branch coverage тоже ускоряется.• concurrency = gevent / eventlet / greenlet и dynamic_context в конфиге: coverage переключается на ctrace.
•
--cov-context=test в pytest-cov: переключения на ctrace нет, и контексты под sysmon теряются. До 7.15.3 это происходило без сообщений, сейчас с предупреждением.• Плагины (Cython, django_coverage_plugin и другие) под
sysmon не работают.• Реализация молодая: исправления для sysmon выходили в 2025-2026 годах (ложные missing branches, KeyError на сложных условиях и except*, падения на Jinja-шаблонах). Держите
coverage.py свежим.Как проверить, что заработало
На 3.14+ sysmon выбран по умолчанию, при конфликтах coverage переключается на ctrace. coverage run
--debug=core покажет, какое ядро реально используется и почему.Как итог:
• 3.14+: ничего не менять, проверить через --debug=core.
• 3.12/3.13, только line coverage: включать.
• 3.12/3.13 с branch coverage: включать бессмысленно.
• Нужны контексты по тестам или плагины: sysmon не подходит.
Документация: coverage.readthedocs.io/en/latest/config.html#run-core