Bazel에는 bazel coverage
로 테스트할 수 있는 저장소에 관한 코드 적용 범위 보고서를 생성하는 coverage
하위 명령어가 있습니다. 다양한 언어 생태계의 특이성으로 인해 특정 프로젝트에서 이 작업을 쉽게 수행할 수 있는 것은 아닙니다.
이 페이지에서는 적용 범위 보고서를 만들고 보기 위한 일반적인 과정을 설명하고 구성이 잘 알려진 언어에 대한 언어별 참고사항도 제공합니다. 먼저 일반 섹션을 읽은 다음 특정 언어의 요구사항을 읽는 것이 가장 좋습니다. 추가 고려사항이 필요한 원격 실행 섹션도 참고하세요.
많은 맞춤설정이 가능하지만 이 문서에서는 현재 가장 잘 지원되는 경로인 lcov
보고서의 생성 및 사용에 중점을 둡니다.
노출 범위 보고서 만들기
준비
적용 범위 보고서를 만드는 기본 워크플로에는 다음이 필요합니다.
- 테스트 대상이 있는 기본 저장소
- 언어별 코드 적용 범위 도구가 설치된 도구 모음
- 올바른 '계측' 구성
앞의 두 가지는 언어별로 다르며 대부분 간단하지만, 후자는 복잡한 프로젝트에서는 더 어려울 수 있습니다.
여기서 '계측'은 특정 타겟에 사용되는 커버리지 도구를 나타냅니다. Bazel은 계측이 사용 설정된 상태에서 테스트되는 타겟의 필터를 지정하는 --instrumentation_filter
플래그를 사용하여 파일의 특정 하위 집합에 이 기능을 사용 설정할 수 있게 해줍니다. 테스트에 계측을 사용 설정하려면 --instrument_test_targets
플래그가 필요합니다.
기본적으로 bazel은 대상 패키지를 일치시키려고 시도하고 관련 필터를 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
는 소스 코드도 읽어서 이러한 파일에서 누락된 적용 범위에 주석을 추가합니다. 이 작업을 수행하려면 bazel 프로젝트의 루트에서 genhtml
가 실행되어야 합니다.
결과를 보려면 웹브라우저의 genhtml
디렉터리에서 생성된 index.html
파일을 열기만 하면 됩니다.
genhtml
도구 또는 lcov
적용 범위 형식에 관한 자세한 도움말과 정보는 lcov 프로젝트를 참고하세요.
원격 실행
원격 테스트 실행으로 실행하는 경우 현재 몇 가지 주의사항이 있습니다.
- 보고서 조합 작업은 아직 원격으로 실행할 수 없습니다. 이는 Bazel에서 노출 영역 출력 파일을 그래프의 일부로 간주하지 않기 때문입니다(이 문제 참고). 따라서 Bazel은 노출 영역 출력 파일을 조합 작업의 입력으로 올바르게 처리할 수 없습니다. 이 문제를 해결하려면
--strategy=CoverageReport=local
를 사용하세요.- 참고: Bazel이 전략을 확인하는 방식으로 인해 Bazel이
local,remote
를 시도하도록 설정된 경우--strategy=CoverageReport=local,remote
와 같은 값을 지정해야 할 수도 있습니다.
- 참고: Bazel이 전략을 확인하는 방식으로 인해 Bazel이
--remote_download_minimal
및 유사한 플래그도 전자의 결과로 사용할 수 없습니다.- 이전에 테스트가 캐시된 경우 Bazel이 현재 커버리지 정보를 생성하지 못합니다. 이 문제를 해결하려면 물론 테스트 시간 측면에서 큰 비용이 발생하지만, 적용 범위 실행을 위해
--nocache_test_results
를 구체적으로 설정할 수 있습니다. --experimental_split_coverage_postprocessing
및--experimental_fetch_all_coverage_outputs
- 일반적으로 적용 범위는 테스트 작업의 일부로 실행되므로 기본적으로 모든 적용 범위가 원격 실행의 출력으로 다시 반환되지는 않습니다. 이러한 플래그는 기본값을 재정의하고 커버리지 데이터를 가져옵니다. 자세한 내용은 이 문제를 참고하세요.
언어별 구성
자바
Java는 기본 구성으로 즉시 작동해야 합니다. bazel 도구 모음에는 JUnit을 비롯하여 원격 실행에 필요한 모든 것이 포함되어 있습니다.
Python
기본 요건
Python으로 적용 범위를 실행하려면 몇 가지 기본 요건이 있습니다.
- b01c859가 포함된 Bazel 바이너리(Bazel 3.0 이상이어야 함)
- covering.py의 수정된 버전
수정된 coverage.py 사용
이를 수행하는 방법은 rules_python을 사용하는 것입니다. 이를 통해 requirements.txt
파일을 사용할 수 있으며, 파일에 나열된 요구사항은 pip_install 저장소 규칙을 사용하여 bazel 타겟으로 생성됩니다.
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",
)
그러면 BUILD
파일에서 다음을 설정하여 테스트 타겟에서 범위.py 요구사항을 사용할 수 있습니다.
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",
],
)
기본 제공 Python 도구 모음을 사용하는 경우 모든 py_test
대상에 적용 범위 종속 항목을 추가하는 대신 도구 모음 구성에 적용 범위 도구를 추가할 수 있습니다.
pip_install 규칙은 Python 도구 모음에 종속되므로 coverage
모듈을 가져오는 데 사용할 수 없습니다.
대신 WORKSPACE
를 추가하세요.예를 들면 다음과 같습니다.
http_archive(
name = "coverage_linux_x86_64"",
build_file_content = """
py_library(
name = "coverage",
srcs = ["coverage/__main__.py"],
data = glob(["coverage/*", "coverage/**/*.py"]),
visibility = ["//visibility:public"],
)
""",
sha256 = "84631e81dd053e8a0d4967cedab6db94345f1c36107c71698f746cb2636c63e3",
type = "zip",
urls = [
"https://files.pythonhosted.org/packages/74/0d/0f3c522312fd27c32e1abe2fb5c323b583a5c108daf2c26d6e8dfdd5a105/coverage-6.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
],
)
그런 다음 다음과 같이 Python 도구 모음을 구성합니다.
py_runtime(
name = "py3_runtime_linux_x86_64",
coverage_tool = "@coverage_linux_x86_64//:coverage",
files = ["@python3_9_x86_64-unknown-linux-gnu//:files"],
interpreter = "@python3_9_x86_64-unknown-linux-gnu//:bin/python3",
python_version = "PY3",
)
py_runtime_pair(
name = "python_runtimes_linux_x86_64",
py2_runtime = None,
py3_runtime = ":py3_runtime_linux_x86_64",
)
toolchain(
name = "python_toolchain_linux_x86_64",
exec_compatible_with = [
"@platforms//os:linux",
"@platforms//cpu:x86_64",
],
toolchain = ":python_runtimes_linux_x86_64",
toolchain_type = "@bazel_tools//tools/python:toolchain_type",
)