बेज़ेल के साथ कोड कवरेज

किसी समस्या की शिकायत करें सोर्स देखें Nightly · 7.4 . 7.3 · 7.2 · 7.1 · 7.0 · 6.5

Bazel में coverage सब-कमांड होता है, जिसकी मदद से उन रिपॉज़िटरी के लिए कोड कवरेज की रिपोर्ट जनरेट की जा सकती हैं जिनकी जांच bazel coverage से की जा सकती है. अलग-अलग भाषा के सिस्टम के हिसाब से, किसी प्रोजेक्ट के लिए इसे इस्तेमाल करना हमेशा आसान नहीं होता.

इस पेज पर, कवरेज रिपोर्ट बनाने और देखने की सामान्य प्रोसेस के बारे में बताया गया है. साथ ही, उन भाषाओं के लिए कुछ खास नोट भी दिए गए हैं जिनका कॉन्फ़िगरेशन अच्छी तरह से जाना जाता है. इसे सबसे पहले सामान्य सेक्शन और फिर किसी खास भाषा की ज़रूरी शर्तों के बारे में पढ़कर पढ़ा जा सकता है. रिमोट तौर पर लागू करने वाले सेक्शन पर भी ध्यान दें. इसके लिए, कुछ और बातों का ध्यान रखना ज़रूरी है.

इस दस्तावेज़ में, lcov रिपोर्ट बनाने और उनका इस्तेमाल करने पर फ़ोकस किया गया है. फ़िलहाल, यह सबसे सही तरीका है. हालांकि, इसमें ज़रूरत के हिसाब से कई बदलाव किए जा सकते हैं.

कवरेज रिपोर्ट बनाना

वीडियो की रणनीति

कवरेज रिपोर्ट बनाने के लिए बुनियादी वर्कफ़्लो के लिए ये ज़रूरी हैं:

  • टेस्ट टारगेट के साथ बुनियादी डेटा स्टोर करने की जगह
  • भाषा के हिसाब से कोड कवरेज टूल इंस्टॉल करने वाला टूलचेन
  • एक सही "इंस्ट्रुमेंटेशन" कॉन्फ़िगरेशन

पहले वाले दो तरीके, खास तौर पर भाषा के हिसाब से हैं और ज़्यादातर आसान हैं. हालांकि, बाद वाले प्रोजेक्ट जटिल प्रोजेक्ट के लिए ज़्यादा मुश्किल हो सकते हैं.

इस मामले में, "इंस्ट्रूमेंटेशन" का मतलब उन कवरेज टूल से है जिनका इस्तेमाल किसी खास टारगेट के लिए किया जाता है. Baze, --instrumentation_filter फ़्लैग का इस्तेमाल करके फ़ाइलों के एक खास सबसेट के लिए इसे चालू करने की अनुमति देता है. इससे, उन टारगेट के लिए एक फ़िल्टर तय होता है जिनकी जांच इंस्ट्रूमेंटेशन के साथ की जाती है. टेस्ट के लिए इंस्ट्रुमेंटेशन चालू करने के लिए, --instrument_test_targets फ़्लैग ज़रूरी है.

डिफ़ॉल्ट रूप से, basel टारगेट पैकेज को मैच करने की कोशिश करता है और ज़रूरत के हिसाब से बने फ़िल्टर को INFO मैसेज के तौर पर प्रिंट करता है.

रनिंग कवरेज

कवरेज रिपोर्ट बनाने के लिए, bazel coverage --combined_report=lcov [target] का इस्तेमाल करें. यह टारगेट के लिए जांच करता है और हर फ़ाइल के लिए lcov फ़ॉर्मैट में कवरेज रिपोर्ट जनरेट करता है.

काम पूरा हो जाने के बाद, बैजल एक ऐसी कार्रवाई करता है जो बनाई गई सभी कवरेज फ़ाइलें इकट्ठा करके, उन्हें एक फ़ाइल में मर्ज कर देती है, जो आखिर में $(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 प्रोजेक्ट के रूट में चलाया जाए.

नतीजा देखने के लिए, genhtml डायरेक्ट्री में बनाई गई index.html फ़ाइल को किसी भी वेब ब्राउज़र में खोलें.

genhtml टूल या lcov कवरेज फ़ॉर्मैट के बारे में ज़्यादा मदद पाने और ज़्यादा जानकारी पाने के लिए, lcov प्रोजेक्ट देखें.

रिमोट से चलाना

रिमोट तरीके से टेस्ट करने की प्रोसेस चलाने के दौरान, फ़िलहाल कुछ चेतावनियां दी गई हैं:

  • रिपोर्ट के कॉम्बिनेशन की कार्रवाई, अभी तक रिमोट तौर पर नहीं चलाई जा सकती. ऐसा इसलिए होता है, क्योंकि Bazel, कवरेज आउटपुट फ़ाइलों को अपने ग्राफ़ का हिस्सा नहीं मानता (यह समस्या देखें). इसलिए, वह इन फ़ाइलों को कॉम्बिनेशन ऐक्शन के इनपुट के तौर पर सही तरीके से इस्तेमाल नहीं कर सकता. इस समस्या को हल करने के लिए, --strategy=CoverageReport=local का इस्तेमाल करें.
    • ध्यान दें: अगर Bazel को local,remote आज़माने के लिए सेट अप किया गया है, तो हो सकता है कि इसके बजाय --strategy=CoverageReport=local,remote जैसा कुछ बताना ज़रूरी हो. ऐसा इसलिए, क्योंकि Bazel रणनीतियों को हल करने का तरीका अपनाता है.
  • --remote_download_minimal और मिलते-जुलते फ़्लैग का इस्तेमाल भी नहीं किया जा सकता.
  • अगर टेस्ट पहले से कैश मेमोरी में सेव किए गए हैं, तो फ़िलहाल Basel, कवरेज की जानकारी नहीं बना पाएगा. इससे बचने के लिए, --nocache_test_results को खास तौर पर, कवरेज चलाने के लिए सेट किया जा सकता है. हालांकि, जांच में लगने वाले समय के हिसाब से, इस सुविधा के लिए आपको भारी शुल्क देना पड़ता है.
  • --experimental_split_coverage_postprocessing और --experimental_fetch_all_coverage_outputs
    • आम तौर पर, कवरेज को टेस्ट ऐक्शन के हिस्से के तौर पर चलाया जाता है. इसलिए, डिफ़ॉल्ट रूप से, हमें रिमोट रन के आउटपुट के तौर पर सारा कवरेज वापस नहीं मिलता. ये फ़्लैग, डिफ़ॉल्ट सेटिंग को बदल देते हैं और कवरेज का डेटा हासिल करते हैं. ज़्यादा जानकारी के लिए, यह समस्या देखें.

भाषा के हिसाब से कॉन्फ़िगरेशन

Java

Java, डिफ़ॉल्ट कॉन्फ़िगरेशन के साथ बिना किसी समस्या के काम करना चाहिए. bazel टूलचेन में, रिमोट तौर पर प्रोग्राम चलाने के लिए ज़रूरी सभी चीज़ें मौजूद होती हैं. इनमें JUnit भी शामिल है.

Python

ज़रूरी शर्तें

Python के साथ कवरेज चलाना, कुछ ज़रूरी शर्तें हैं:

बदली गई कवरेज का इस्तेमाल करना

ऐसा करने का एक तरीका 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 toolchain पर निर्भर करता है. इसलिए, इसका इस्तेमाल 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",
)