Cobertura de código con Bazel

Informar un problema Ver fuente . Por la noche · 7.3 · 7.2 · 7.1 · 7.0 · 6.5

Bazel cuenta con un subcomando coverage para producir cobertura de código. Informes sobre repositorios que se pueden probar con bazel coverage. Venc. a las idiosincrasias de los diversos ecosistemas lingüísticos, siempre es trivial para que esto funcione en un proyecto determinado.

En esta página, se documenta el proceso general de creación y visualización informes de cobertura y también incluye algunas notas específicas del idioma para lenguajes de programación cuya configuración es conocida. Se recomienda leer primero leer la sección general y, luego, leyendo sobre los requisitos de un lenguaje específico. Ten en cuenta también sección de ejecución remota, que requiere consideraciones adicionales.

Si bien es posible realizar una gran cantidad de personalización, este documento se centra en produce y consume informes de lcov, que actualmente es el la ruta más compatible.

Cómo crear un informe de cobertura

Preparación

El flujo de trabajo básico para crear informes de cobertura requiere la lo siguiente:

  • Un repositorio básico con objetivos de prueba
  • Una cadena de herramientas con las herramientas de cobertura de código específicas del lenguaje instaladas
  • Una “instrumentación” correcta configuración

Las dos primeras son específicas del lenguaje y, en su mayoría, sencillas, Sin embargo, este último puede ser más difícil en proyectos complejos.

"Instrumentación" en este caso, a las herramientas de cobertura usarse para un objetivo específico. Bazel permite activar esta función para un subconjunto específico de archivos con el --instrumentation_filter marca, que especifica un filtro para los objetivos que se prueban con el instrumentación habilitada. Para habilitar la instrumentación para pruebas, --instrument_test_targets es obligatoria.

De forma predeterminada, bazel intenta hacer coincidir los paquetes de destino y, luego, imprime los relevante como un mensaje INFO.

Cobertura para correr

Para crear un informe de cobertura, usa bazel coverage --combined_report=lcov [target]. Esto ejecuta el pruebas para la orientación y la generación de informes de cobertura en formato lcov para cada archivo.

Cuando termina, Bazel ejecuta una acción que recopila todo lo que archivos de cobertura y los combina en uno, que finalmente creada con $(bazel info output_path)/_coverage/_coverage_report.dat.

Los informes de cobertura también se generan si las pruebas fallan. Sin embargo, ten en cuenta que Esto no se extiende a las pruebas fallidas, solo se aprueban informes.

Cómo ver la cobertura

El informe de cobertura solo se genera en un formato no legible por humanos lcov de un conjunto de datos tengan un formato común. Desde esto, podemos usar la utilidad genhtml (parte de lcov proyecto) para generar un informe que se pueda ver en una navegador:

genhtml --output genhtml "$(bazel info output_path)/_coverage/_coverage_report.dat"

Ten en cuenta que genhtml también lee el código fuente para anotar que falta cobertura en estos archivos. Para que esto funcione, se espera que genhtml se ejecuta en la raíz del proyecto de Bazel.

Para ver el resultado, simplemente abre el archivo index.html generado en genhtml en cualquier navegador web.

Para obtener más información y ayuda sobre la herramienta genhtml o Formato de cobertura de lcov; consulta el proyecto lcov.

Ejecución remota

La ejecución con la ejecución de prueba remota actualmente tiene algunas advertencias:

  • La acción de combinación de informes todavía no se puede ejecutar de forma remota. Este es ya que Bazel no considera los archivos de salida de cobertura como parte en su gráfico (consulta este problema) y, por lo tanto, puede no las tratan correctamente como entradas en la acción de combinación. Para solucionar esto, usa --strategy=CoverageReport=local.
    • Nota: Tal vez sea necesario especificar --strategy=CoverageReport=local,remote en su lugar, si Bazel está configurado para probar local,remote, debido a la forma en que Bazel resuelve las estrategias.
  • Tampoco se pueden usar --remote_download_minimal ni marcas similares. como consecuencia de lo primero.
  • Por el momento, Bazel no podrá crear información de cobertura si se realizan pruebas. se almacenaron en caché anteriormente. Para solucionar esto, --nocache_test_results se puede configurar específicamente para ejecuciones de cobertura, aunque esto, por supuesto, genera un alto costo en términos de tiempos de prueba.
  • --experimental_split_coverage_postprocessing y --experimental_fetch_all_coverage_outputs
    • Por lo general, la cobertura se realiza como parte de la acción de prueba. de forma predeterminada, no obtenemos toda la cobertura como salida del ejecución de forma predeterminada. Estas marcas anulan el valor predeterminado y obtienen los datos de cobertura. Consulta este problema para obtener más información más detalles.

Configuración de lenguaje específico

Java

Java debería funcionar de inmediato con la configuración predeterminada. El Las cadenas de herramientas de bazel contienen todo lo necesario para ejecución remota, incluida JUnit.

Python

Requisitos previos

La ejecución de cobertura con Python tiene algunos requisitos previos:

Cómo consumir la cover.py modificada

Una forma de hacerlo es mediante rules_python, que proporciona la capacidad de usar un archivo requirements.txt, los requisitos enumerados del archivo se crean como destinos de Bazel con el pip_install.

requirements.txt debe tener la siguiente entrada:

git+https://github.com/ulfjack/coveragepy.git@lcov-support

Los archivos rules_python, pip_install y requirements.txt deben usarse en el archivo WORKSPACE de la siguiente manera:

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",
)

Los objetivos de prueba pueden usar el requisito deCover.py Configura lo siguiente en los archivos 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",
    ],
)

Si estás usando una cadena de herramientas hermética de Python, en lugar de agregar la cobertura dependencia a cada objetivo de py_test, puedes agregar la herramienta de cobertura a la configuración de la cadena de herramientas.

Debido a que la regla pip_install depende de Python, no se puede usar para recuperar el módulo coverage. En su lugar, agrega tu WORKSPACE, p.ej.,

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",
    ],
)

Luego, configura tu cadena de herramientas de Python, p.ej.,

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",
)