Cakupan kode dengan Bazel

Tetap teratur dengan koleksi Simpan dan kategorikan konten berdasarkan preferensi Anda.
Laporkan masalah Lihat sumber

Bazel menampilkan sub-perintah coverage untuk menghasilkan laporan cakupan kode pada repositori yang dapat diuji dengan bazel coverage. Karena ketidaksesuaian berbagai ekosistem bahasa, tidak selalu mudah untuk membuatnya berfungsi untuk project tertentu.

Halaman ini mendokumentasikan proses umum untuk membuat dan melihat laporan cakupan, serta menampilkan beberapa catatan khusus bahasa untuk bahasa yang konfigurasinya sudah terkenal. Sebaiknya baca dengan membaca bagian umum terlebih dahulu, lalu membaca persyaratan bahasa tertentu. Perhatikan juga bagian eksekusi jarak jauh, yang memerlukan beberapa pertimbangan tambahan.

Meskipun banyak penyesuaian dapat dilakukan, dokumen ini berfokus pada pembuatan dan pemakaian laporan lcov, yang saat ini merupakan rute yang paling didukung dengan baik.

Membuat laporan cakupan

Persiapan

Alur kerja dasar untuk membuat laporan cakupan memerlukan hal berikut:

  • Repositori dasar dengan target pengujian
  • Toolchain dengan alat cakupan kode bahasa tertentu yang terinstal
  • Konfigurasi "instrumentasi" yang benar

Keduanya memerlukan bahasa tertentu dan sebagian besar sederhana, tetapi yang terakhir dapat lebih sulit untuk project yang kompleks.

Dalam kasus ini, "Instrumentasi" mengacu pada alat cakupan yang digunakan untuk target tertentu. Bazel memungkinkan pengaktifan ini untuk subkumpulan file tertentu menggunakan flag --instrumentation_filter, yang menentukan filter untuk target yang diuji dengan instrumentasi yang diaktifkan. Untuk mengaktifkan instrumentasi pengujian, flag --instrument_test_targets diperlukan.

Secara default, Bazel mencoba mencocokkan paket target, dan mencetak filter yang relevan sebagai pesan INFO.

Cakupan yang berjalan

Untuk membuat laporan cakupan, gunakan bazel coverage --combined_report=lcov [target]. Tindakan ini akan menjalankan pengujian untuk target, sehingga menghasilkan laporan cakupan dalam format lcov untuk setiap file.

Setelah selesai, bazel menjalankan tindakan yang mengumpulkan semua file cakupan yang dihasilkan, dan menggabungkannya menjadi satu, yang akhirnya dibuat di bagian $(bazel info output_path)/_coverage/_coverage_report.dat.

Laporan cakupan juga dibuat jika pengujian gagal, meskipun perhatikan bahwa laporan ini tidak mencakup pengujian yang gagal; hanya pengujian yang lulus yang akan dilaporkan.

Cakupan tampilan

Laporan cakupan hanya berupa output dalam format lcov yang tidak dapat dibaca manusia. Dari sini, kita dapat menggunakan utilitas genhtml (bagian dari project lcov) untuk menghasilkan laporan yang dapat dilihat di browser web:

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

Perhatikan bahwa genhtml juga membaca kode sumber untuk menganotasi cakupan yang hilang dalam file ini. Agar berfungsi, diharapkan genhtml dijalankan di root project bazel.

Untuk melihat hasilnya, cukup buka file index.html yang dihasilkan dalam direktori genhtml di browser web apa pun.

Untuk mendapatkan bantuan dan informasi lebih lanjut seputar alat genhtml, atau format cakupan lcov, lihat project lcov.

Eksekusi jarak jauh

Menjalankan dengan eksekusi uji jarak jauh saat ini memiliki beberapa peringatan:

  • Tindakan kombinasi laporan belum dapat dijalankan dari jarak jauh. Hal ini karena Bazel tidak menganggap file output cakupan sebagai bagian dari grafiknya (lihat masalah ini), sehingga tidak dapat memperlakukannya dengan benar sebagai input untuk tindakan kombinasi. Untuk mengatasi masalah ini, gunakan --strategy=CoverageReport=local.
    • Catatan: Anda mungkin perlu menentukan sesuatu seperti --strategy=CoverageReport=local,remote, jika Bazel disiapkan untuk mencoba local,remote, karena cara Bazel menyelesaikan strategi.
  • --remote_download_minimal dan flag serupa juga tidak dapat digunakan sebagai konsekuensi dari flag sebelumnya.
  • Bazel saat ini akan gagal membuat informasi cakupan jika pengujian telah di-cache sebelumnya. Untuk mengatasi hal ini, --nocache_test_results dapat ditetapkan secara khusus untuk menjalankan cakupan, meskipun hal ini tentu saja memerlukan biaya yang tinggi dalam hal waktu pengujian.
  • --experimental_split_coverage_postprocessing dan --experimental_fetch_all_coverage_outputs
    • Biasanya cakupan dijalankan sebagai bagian dari tindakan pengujian, sehingga secara default, kami tidak mendapatkan semua cakupan kembali sebagai output eksekusi jarak jauh secara default. Flag ini mengganti default dan mendapatkan data cakupan. Lihat masalah ini untuk mengetahui detail selengkapnya.

Konfigurasi khusus bahasa

Java

Java akan langsung berfungsi dengan konfigurasi default. Toolchain Bazel berisi semua hal yang diperlukan untuk eksekusi jarak jauh juga, termasuk JUnit.

Python

Prasyarat

Cakupan yang berjalan dengan python memiliki beberapa prasyarat:

Memakai cakupan.py yang diubah

Cara melakukannya adalah melalui rules_python, yang memberi kemampuan untuk menggunakan file requirements.txt. Persyaratan yang tercantum dalam file kemudian dibuat sebagai target bazel menggunakan aturan repositori pip_install.

requirements.txt harus memiliki entri berikut:

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

Kemudian, file rules_python, pip_install, dan requirements.txt kemudian harus digunakan di file WORKSPACE sebagai:

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

Persyaratan cakupan.py kemudian dapat digunakan oleh target pengujian dengan menetapkan hal berikut dalam file 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",
    ],
)

Jika menggunakan toolchain Python hermetic, daripada menambahkan dependensi cakupan ke setiap target py_test, Anda dapat menambahkan alat cakupan ke konfigurasi toolchain.

Karena aturan pip_install bergantung pada toolchain Python, aturan tidak dapat digunakan untuk mengambil modul coverage. Sebagai gantinya, tambahkan WORKSPACE Anda mis.

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

Kemudian, konfigurasikan toolchain python Anda, misalnya

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