Короткий ответ
Покрытие показывает, какая доля строк или веток кода была выполнена хотя бы одним тестом, но не проверяет, что тест действительно содержит осмысленные проверки (assert) ожидаемого поведения на этих строках.
Как это работает подробнее
Инструмент вроде pytest-cov инструментирует код во время прогона тестов и фиксирует, какие строки (line coverage) или ветки условий (branch coverage) были выполнены хотя бы один раз, формируя отчёт в процентах по отдельным файлам, модулям и проекту в целом, с подсветкой непокрытых строк.
Пример кода
testing_example_302.py
# плохой пример: строка покрыта, но ничего не проверяется
def test_process_order_runs_without_errors():
process_order(Order(items=[])) # нет ни одного assert
# лучше:
def test_process_order_returns_zero_total_for_empty_order():
result = process_order(Order(items=[]))
assert result.total == 0Что использовать на практике
- Практика. Покрытие полезно, чтобы найти явно непротестированный код — функции или ветки обработки ошибок, которые вообще ни разу не вызывались в тестах. Но тест, который просто вызывает функцию без содержательного assert, засчитает строки как покрытые, хотя фактически ничего не проверил о корректности поведения.
Подводные камни
- Риск. Ставить цель «100% покрытия» как самоцель, что приводит к формальным тестам без содержательных проверок, написанным только ради зелёной метрики. Делать выводы о качестве кода только по общему проценту покрытия проекта, не глядя на то, какие именно критичные ветки (обработка ошибок, граничные значения, редкие сценарии) остались непокрытыми.