Что такое Coverage.py
Coverage.py — это мощный инструмент для анализа покрытия кода тестами в Python, который позволяет разработчикам определить, какие части их кода выполнялись во время тестирования, а какие остались неиспользованными. Этот инструмент является неотъемлемой частью процесса обеспечения качества кода и помогает выявить потенциальные проблемы в тестовом покрытии.
Основная цель Coverage.py — предоставить детальную информацию о том, насколько полно ваши тесты покрывают написанный код. Инструмент анализирует выполнение программы и создает отчеты, показывающие процент покрытия для каждого файла, модуля или даже отдельных строк кода.
Ключевые возможности Coverage.py
Coverage.py предоставляет широкий спектр функций для анализа покрытия кода:
Измерение покрытия строк — базовая функция, которая отслеживает, какие строки кода были выполнены во время тестирования.
Анализ ветвлений — расширенная функция, которая проверяет, были ли выполнены все возможные пути выполнения в условных конструкциях (if, elif, else).
Генерация отчетов — создание детальных отчетов в различных форматах: текстовом, HTML, XML, JSON.
Интеграция с фреймворками — seamless работа с популярными тестовыми фреймворками, такими как pytest, unittest, nose.
Настройка исключений — возможность исключать определенные файлы, папки или строки из анализа покрытия.
Установка и начальная настройка
Стандартная установка
Для установки Coverage.py используйте pip:
pip install coverage
Установка с дополнительными возможностями
Если вы работаете с pytest, рекомендуется установить плагин pytest-cov:
pip install pytest-cov
Для работы с toml-файлами конфигурации:
pip install coverage[toml]
Проверка установки
После установки убедитесь, что Coverage.py работает корректно:
coverage --version
Основные команды и их использование
Запуск анализа покрытия
Базовый запуск анализа покрытия для Python-скрипта:
coverage run my_script.py
Запуск с дополнительными параметрами:
coverage run --source=my_package my_script.py
Запуск с модулем unittest
coverage run -m unittest discover
Запуск с pytest
coverage run -m pytest
Или используя pytest-cov:
pytest --cov=my_module tests/
Просмотр отчета покрытия
Текстовый отчет в терминале
coverage report
Пример вывода:
Name Stmts Miss Cover
----------------------------------------
my_module.py 25 3 88%
utils.py 15 0 100%
main.py 20 5 75%
----------------------------------------
TOTAL 60 8 87%
Детальный отчет с пропущенными строками
coverage report --show-missing
HTML-отчет
coverage html
После выполнения команды откройте файл htmlcov/index.html в браузере для просмотра интерактивного отчета.
XML-отчет для CI/CD
coverage xml
JSON-отчет
coverage json
Управление данными покрытия
Очистка данных
coverage erase
Объединение данных
coverage combine
Таблица основных методов и функций Coverage.py
| Команда | Назначение | Основные параметры |
|---|---|---|
coverage run |
Запуск программы с измерением покрытия | --source, --omit, --include, --branch |
coverage report |
Генерация текстового отчета | --show-missing, --skip-covered, --include, --omit |
coverage html |
Создание HTML-отчета | --directory, --include, --omit, --title |
coverage xml |
Генерация XML-отчета | --include, --omit, -o |
coverage json |
Создание JSON-отчета | --include, --omit, -o |
coverage erase |
Удаление данных покрытия | Нет параметров |
coverage combine |
Объединение данных покрытия | --append, --keep |
coverage annotate |
Создание аннотированного кода | --include, --omit, --directory |
coverage debug |
Отладочная информация | data, sys, config |
Конфигурация Coverage.py
Файл .coveragerc
Создайте файл .coveragerc в корне проекта для настройки Coverage.py:
[run]
# Включить анализ ветвлений
branch = True
# Указать источники для анализа
source = my_package
# Исключить файлы из анализа
omit =
*/tests/*
*/migrations/*
*/__init__.py
*/venv/*
*/env/*
setup.py
# Параллельное выполнение
parallel = True
[report]
# Показать пропущенные строки
show_missing = True
# Пропустить файлы с 100% покрытием
skip_covered = False
# Минимальный процент покрытия
fail_under = 80
# Точность процентов
precision = 2
# Исключить строки с комментариями
exclude_lines =
pragma: no cover
def __repr__
if self.debug:
if settings.DEBUG
raise AssertionError
raise NotImplementedError
if 0:
if __name__ == .__main__.:
class .*\bProtocol\):
@(abc\.)?abstractmethod
[html]
# Директория для HTML-отчета
directory = htmlcov
# Заголовок отчета
title = Coverage Report
[xml]
# Файл для XML-отчета
output = coverage.xml
Конфигурация через pyproject.toml
Современный подход с использованием pyproject.toml:
[tool.coverage.run]
branch = true
source = ["my_package"]
omit = [
"*/tests/*",
"*/migrations/*",
"*/__init__.py",
]
[tool.coverage.report]
show_missing = true
skip_covered = false
fail_under = 80
precision = 2
exclude_lines = [
"pragma: no cover",
"def __repr__",
"if self.debug:",
"if settings.DEBUG",
"raise AssertionError",
"raise NotImplementedError",
"if 0:",
"if __name__ == .__main__.:",
]
[tool.coverage.html]
directory = "htmlcov"
title = "Coverage Report"
[tool.coverage.xml]
output = "coverage.xml"
Анализ покрытия ветвлений
Что такое покрытие ветвлений
Покрытие ветвлений (branch coverage) — это более продвинутый тип анализа, который проверяет, были ли выполнены все возможные пути в условных конструкциях.
Включение анализа ветвлений
В файле конфигурации:
[run]
branch = True
Или через командную строку:
coverage run --branch my_script.py
Пример анализа ветвлений
def check_number(x):
if x > 0:
return "positive"
elif x < 0:
return "negative"
else:
return "zero"
Без покрытия ветвлений может показаться, что функция полностью покрыта, если вызвать её с положительным числом. Но анализ ветвлений покажет, что не все условия были проверены.
Интеграция с тестовыми фреймворками
Работа с pytest
Базовое использование
pytest --cov=my_package
Генерация HTML-отчета
pytest --cov=my_package --cov-report html
Установка минимального порога покрытия
pytest --cov=my_package --cov-fail-under=90
Комбинирование различных типов отчетов
pytest --cov=my_package --cov-report html --cov-report term --cov-report xml
Работа с unittest
coverage run -m unittest discover
coverage report
coverage html
Работа с nose
coverage run -m nose
coverage report
Исключение кода из анализа
Использование pragma комментариев
def debug_function():
print("Debug information") # pragma: no cover
def main():
if DEBUG: # pragma: no cover
debug_function()
# остальной код
Исключение целых блоков
# pragma: no cover
def development_only_function():
pass
class DebugClass: # pragma: no cover
def __init__(self):
pass
Исключение через конфигурацию
В .coveragerc:
[run]
omit =
*/tests/*
*/debug.py
*/development/*
Работа с отчетами
Понимание HTML-отчетов
HTML-отчет предоставляет наиболее детальную информацию о покрытии:
- Зеленые строки — выполнялись во время тестирования
- Красные строки — не выполнялись
- Желтые строки — частично выполнялись (в случае ветвлений)
Анализ метрик покрытия
- Statements — общее количество исполняемых строк
- Missing — количество неиспользованных строк
- Coverage — процент покрытия
- Branch — информация о покрытии ветвлений
Интеграция с CI/CD системами
GitHub Actions
name: Tests with Coverage
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: Install dependencies
run: |
pip install -r requirements.txt
pip install coverage
- name: Run tests with coverage
run: |
coverage run -m pytest
coverage report
coverage xml
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v1
with:
file: ./coverage.xml
GitLab CI
test:
stage: test
script:
- pip install -r requirements.txt
- pip install coverage
- coverage run -m pytest
- coverage report
- coverage xml
coverage: '/TOTAL.*\s+(\d+%)$/'
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: coverage.xml
Jenkins
pipeline {
agent any
stages {
stage('Test') {
steps {
sh 'pip install -r requirements.txt'
sh 'pip install coverage'
sh 'coverage run -m pytest'
sh 'coverage report'
sh 'coverage xml'
}
}
}
post {
always {
publishHTML([
allowMissing: false,
alwaysLinkToLastBuild: true,
keepAll: true,
reportDir: 'htmlcov',
reportFiles: 'index.html',
reportName: 'Coverage Report'
])
}
}
}
Интеграция с IDE
PyCharm
PyCharm Professional имеет встроенную поддержку Coverage.py:
- Откройте Run/Debug Configurations
- Выберите конфигурацию тестов
- Перейдите на вкладку Coverage
- Включите Code Coverage
- Настройте параметры покрытия
Visual Studio Code
Для VS Code доступны расширения:
- Python Test Explorer — для запуска тестов с покрытием
- Coverage Gutters — для отображения покрытия в редакторе
Настройка в settings.json:
{
"python.testing.pytestEnabled": true,
"python.testing.pytestArgs": [
"--cov=my_package",
"--cov-report=html"
]
}
Продвинутые возможности
Параллельное выполнение
Для проектов с параллельным выполнением тестов:
[run]
parallel = True
После выполнения тестов объедините результаты:
coverage combine
coverage report
Плагины и расширения
Coverage.py поддерживает систему плагинов для расширения функциональности:
- django_coverage_plugin — для Django проектов
- pytest-cov — интеграция с pytest
- coverage-badge — генерация badges для README
Программный API
Coverage.py можно использовать программно:
import coverage
# Создание объекта coverage
cov = coverage.Coverage()
# Начало измерения
cov.start()
# Ваш код здесь
import my_module
my_module.some_function()
# Остановка измерения
cov.stop()
# Сохранение данных
cov.save()
# Генерация отчета
cov.report()
Оптимизация производительности
Уменьшение времени выполнения
- Используйте параметр
--sourceдля ограничения анализа - Исключайте ненужные файлы через
omit - Используйте параллельное выполнение для больших проектов
Настройка для больших проектов
[run]
# Ограничить анализ основным пакетом
source = my_package
# Исключить библиотеки и тестовые файлы
omit =
*/site-packages/*
*/tests/*
*/migrations/*
*/venv/*
# Использовать параллельное выполнение
parallel = True
# Оптимизировать использование памяти
concurrency = multiprocessing
Часто задаваемые вопросы
Как настроить Coverage.py для Django проекта?
Для Django проектов рекомендуется использовать django_coverage_plugin:
pip install django_coverage_plugin
В .coveragerc:
[run]
plugins = django_coverage_plugin
source = .
omit =
*/migrations/*
*/venv/*
*/env/*
manage.py
*/settings/*
*/tests/*
Почему Coverage.py показывает низкое покрытие?
Низкое покрытие может быть вызвано:
- Недостаточным количеством тестов
- Наличием мертвого кода
- Неправильной конфигурацией (включение ненужных файлов)
- Отсутствием тестов для исключительных ситуаций
Как исключить определенные строки из анализа?
Используйте комментарий # pragma: no cover или настройте exclude_lines в конфигурации:
[report]
exclude_lines =
pragma: no cover
def __repr__
raise AssertionError
raise NotImplementedError
Можно ли использовать Coverage.py для измерения покрытия в продакшене?
Не рекомендуется использовать Coverage.py в продакшене, так как это значительно снижает производительность. Используйте его только для тестирования и разработки.
Как интегрировать Coverage.py с pre-commit хуками?
Создайте файл .pre-commit-config.yaml:
repos:
- repo: local
hooks:
- id: coverage
name: coverage
entry: coverage run -m pytest
language: system
pass_filenames: false
always_run: true
Что означает "partial" покрытие в отчетах?
Partial покрытие означает, что не все ветви условного оператора были выполнены. Например, в конструкции if-else была выполнена только одна ветвь.
Лучшие практики
Рекомендации по целевому покрытию
- 80-90% — хорошее покрытие для большинства проектов
- 100% — не всегда необходимо и может привести к избыточному тестированию
- Сосредоточьтесь на критически важных частях кода
Правила написания тестов
- Тестируйте как положительные, так и отрицательные сценарии
- Включайте тесты для граничных случаев
- Не забывайте о тестировании исключительных ситуаций
Поддержка качества кода
- Регулярно просматривайте отчеты покрытия
- Используйте Coverage.py в процессе code review
- Настройте автоматические проверки в CI/CD
Альтернативы и дополнения
Сравнение с другими инструментами
- pytest-cov — плагин для pytest, основанный на Coverage.py
- nose-cov — плагин для nose
- mutmut — инструмент для мутационного тестирования
Дополнительные инструменты
- Codecov — облачный сервис для анализа покрытия
- Coveralls — альтернативный облачный сервис
- SonarQube — комплексный анализ качества кода
Заключение
Coverage.py является незаменимым инструментом для поддержания высокого качества кода в Python проектах. Он предоставляет детальную информацию о покрытии тестами, помогает выявлять неиспользуемый код и улучшать качество тестирования.
Правильное использование Coverage.py в сочетании с хорошими практиками тестирования позволяет создавать более надежные и поддерживаемые приложения. Инструмент особенно ценен в командной разработке, где важно поддерживать единые стандарты качества кода.
Помните, что высокое покрытие кода — это не самоцель, а средство для достижения лучшего качества программного обеспечения. Используйте Coverage.py как часть комплексного подхода к обеспечению качества, включающего code review, статический анализ и другие практики современной разработки.
Настоящее и будущее развития ИИ: классической математики уже недостаточно
Эксперты предупредили о рисках фейковой благотворительности с помощью ИИ
В России разработали универсального ИИ-агента для роботов и индустриальных процессов