Coverage.py – проверка покрытия кода тестами

онлайн тренажер по питону
Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Что такое 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:

  1. Откройте Run/Debug Configurations
  2. Выберите конфигурацию тестов
  3. Перейдите на вкладку Coverage
  4. Включите Code Coverage
  5. Настройте параметры покрытия

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, статический анализ и другие практики современной разработки.

Новости