پوشش کد با بازل

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
    • معمولاً پوشش به عنوان بخشی از عمل آزمایشی اجرا می‌شود، و بنابراین به‌طور پیش‌فرض، ما به‌طور پیش‌فرض همه پوشش‌ها را به عنوان خروجی‌های اجرای از راه دور بر نمی‌گردانیم. این پرچم ها پیش فرض را لغو می کنند و داده های پوشش را به دست می آورند. برای جزئیات بیشتر به این شماره مراجعه کنید.

پیکربندی خاص زبان

جاوا

جاوا باید خارج از جعبه با پیکربندی پیش فرض کار کند. زنجیره‌های ابزار بازل شامل همه چیزهایی هستند که برای اجرای از راه دور لازم است، از جمله JUnit.

پایتون

پیش نیازها

اجرای پوشش با پایتون چند پیش نیاز دارد:

مصرف coverage.py اصلاح شده

راهی برای انجام این کار از طریق rules_python است، این امکان استفاده از یک فایل requires.txt را فراهم می کند، requirements.txt فهرست شده در فایل سپس با استفاده از قانون مخزن pip_install به عنوان اهداف bazel ایجاد می شوند.

requirements.txt .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 ، نیازمندی coverage.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 به زنجیره ابزار پایتون بستگی دارد، نمی توان از آن برای واکشی ماژول 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",
    ],
)

سپس زنجیره ابزار پایتون خود را به عنوان مثال پیکربندی کنید

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