В Bazel есть подкоманда coverage
для создания отчетов о покрытии кода в репозиториях, которые можно протестировать с bazel coverage
. Из-за особенностей различных языковых экосистем не всегда просто сделать так, чтобы это работало для данного проекта.
На этой странице описан общий процесс создания и просмотра отчетов о покрытии, а также приведены некоторые примечания, относящиеся к языку, конфигурация которых хорошо известна. Лучше всего читать сначала общий раздел , а потом читать о требованиях к конкретному языку. Обратите также внимание на раздел удаленного выполнения , который требует некоторых дополнительных соображений.
Несмотря на то, что возможна большая настройка, этот документ посвящен созданию и использованию отчетов lcov
, что в настоящее время является наиболее хорошо поддерживаемым маршрутом.
Создание отчета о покрытии
Подготовка
Базовый рабочий процесс для создания отчетов о покрытии требует следующего:
- Базовый репозиторий с тестовыми целями
- Цепочка инструментов с установленными инструментами покрытия кода для конкретного языка.
- Правильная "приборная" конфигурация
Первые два зависят от языка и в основном просты, однако последний может быть более сложным для сложных проектов.
«Инструментарий» в данном случае относится к инструментам покрытия, которые используются для конкретной цели. Bazel позволяет включить это для определенного подмножества файлов с помощью флага --instrumentation_filter
, который указывает фильтр для целей, тестируемых с включенным инструментарием. Чтобы включить инструменты для тестов, требуется флаг --instrument_test_targets
.
По умолчанию INFO
пытается сопоставить целевые пакеты и выводит соответствующий фильтр в виде информационного сообщения.
Беговое покрытие
Чтобы создать отчет о покрытии, используйте bazel coverage --combined_report=lcov [target]
. Это запускает тесты для цели, создавая отчеты о покрытии в формате lcov для каждого файла.
После завершения bazel запускает действие, которое собирает все созданные файлы покрытия и объединяет их в один, который затем, наконец, создается в $(bazel info output_path)/_coverage/_coverage_report.dat
.
Отчеты о покрытии также создаются, если тесты не пройдены, хотя обратите внимание, что это не распространяется на неудачные тесты — сообщается только о прохождении тестов.
Просмотр покрытия
Отчет о покрытии выводится только в неудобочитаемом формате lcov
. Исходя из этого, мы можем использовать утилиту genhtml
(часть проекта lcov ) для создания отчета, который можно просмотреть в веб-браузере:
genhtml --output genhtml "$(bazel info output_path)/_coverage/_coverage_report.dat"
Обратите внимание, что genhtml
читает исходный код, чтобы аннотировать отсутствующее покрытие в этих файлах. Чтобы это работало, ожидается, что genhtml
выполняется в корне проекта bazel.
Чтобы просмотреть результат, просто откройте файл index.html
, созданный в каталоге genhtml
в любом веб-браузере.
Для получения дополнительной помощи и информации об инструменте genhtml
или формате покрытия lcov
см. проект lcov .
Удаленное исполнение
Запуск с удаленным выполнением тестов в настоящее время имеет несколько предостережений:
- Действие объединения отчетов пока не может выполняться удаленно. Это связано с тем, что Bazel не рассматривает выходные файлы покрытия как часть своего графа (см. этот выпуск ) и, следовательно, не может правильно рассматривать их как входные данные для действия объединения. Чтобы обойти это, используйте
--strategy=CoverageReport=local
.- Примечание. Может потребоваться указать что-то вроде
--strategy=CoverageReport=local,remote
вместо этого, если Bazel настроен на попыткуlocal,remote
из-за того, как Bazel разрешает стратегии.
- Примечание. Может потребоваться указать что-то вроде
-
--remote_download_minimal
и подобные флаги также нельзя использовать как следствие первого. - В настоящее время Bazel не сможет создать информацию о покрытии, если тесты ранее были кэшированы. Чтобы обойти это,
--nocache_test_results
может быть установлен специально для прогонов покрытия, хотя это, конечно, влечет за собой большие затраты с точки зрения времени тестирования. -
--experimental_split_coverage_postprocessing
и--experimental_fetch_all_coverage_outputs
- Обычно покрытие запускается как часть тестового действия, поэтому по умолчанию мы не получаем все покрытие обратно в виде результатов удаленного выполнения по умолчанию. Эти флаги переопределяют значения по умолчанию и получают данные о покрытии. Подробнее см. в этом выпуске .
Конфигурация для конкретного языка
Джава
Java должна работать «из коробки» с конфигурацией по умолчанию. Инструментальные цепочки bazel также содержат все необходимое для удаленного выполнения, включая JUnit.
Питон
Предпосылки
Запуск покрытия с помощью python требует некоторых предварительных условий:
- Двоичный файл Bazel, включающий b01c859 , который должен быть любым Bazel > 3.0.
- Модифицированная версияcoverage.py .
Использование измененного покрытия.py
Это можно сделать с помощью rules_python , это дает возможность использовать файл requirements.txt
, требования, перечисленные в файле, затем создаются как цели bazel с использованием правила репозитория pip_install .
В requirements.txt
должна быть следующая запись:
git+https://github.com/ulfjack/coveragepy.git@lcov-support
rules_python
, pip_install
и файл requirements.txt
следует использовать в файле WORKSPACE как:
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "rules_python",
url = "https://github.com/bazelbuild/rules_python/releases/download/0.5.0/rules_python-0.5.0.tar.gz",
sha256 = "cd6730ed53a002c56ce4e2f396ba3b3be262fd7cb68339f0377a45e8227fe332",
)
load("@rules_python//python:pip.bzl", "pip_install")
pip_install(
name = "python_deps",
requirements = "//:requirements.txt",
)
Требование cover.py затем может быть использовано целевыми объектами тестирования путем установки следующих параметров в файлах BUILD
:
load("@python_deps//:requirements.bzl", "entry_point")
alias(
name = "python_coverage_tools",
actual = entry_point("coverage"),
)
py_test(
name = "test",
srcs = ["test.py"],
env = {
"PYTHON_COVERAGE": "$(location :python_coverage_tools)",
},
deps = [
":main",
":python_coverage_tools",
],
)