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

समस्या की शिकायत करें सोर्स देखें

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

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

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

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

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

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

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

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

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

डिफ़ॉल्ट रूप से, बैज टारगेट पैकेज को मैच करने की कोशिश करता है और ज़रूरत के हिसाब से बने फ़िल्टर को 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 को बेज़ल प्रोजेक्ट के रूट में लागू किया गया है.

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

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

रिमोट तरीके से एक्ज़ीक्यूट करें

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

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

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

Java

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

Python

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

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

संशोधित कवरेज.py का इस्तेमाल करना

ऐसा करने का तरीका rules_python की मदद से इस्तेमाल किया जा सकता है. इससे requirements.txt फ़ाइल इस्तेमाल की जा सकती है. इसके बाद, फ़ाइल में बताई गई ज़रूरी शर्तों को pip_install डेटा संग्रह स्थान नियम का इस्तेमाल करके बेज़ल टारगेट के तौर पर बनाया जाता है.

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

अगर हर py_test टारगेट के लिए कवरेज डिपेंडेंसी जोड़ने के बजाय हर्मेटिक Python टूलचेन का इस्तेमाल किया जा रहा है, तो आपके पास टूलचेन कॉन्फ़िगरेशन में कवरेज टूल जोड़ने का विकल्प है.

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