Bazel, डेटा स्टोर करने की जगहों पर ऐसी कोड कवरेज रिपोर्ट बनाने के लिए, coverage
सब-कमांड देता है जिसकी जांच bazel coverage
की मदद से की जा सकती है. अलग-अलग भाषा के इकोसिस्टम की खास पहचान की वजह से, किसी प्रोजेक्ट में ऐसा करना हमेशा आसान नहीं होता.
इस पेज में कवरेज रिपोर्ट बनाने और उन्हें देखने की सामान्य प्रक्रिया बताई गई है. साथ ही, उन भाषाओं के लिए भाषा के हिसाब से कुछ नोट भी दिए गए हैं जिनका कॉन्फ़िगरेशन जाना-पहचाना है. सबसे अच्छे तरीके से, पहले सामान्य सेक्शन को पढ़ें और फिर किसी खास भाषा से जुड़ी ज़रूरी शर्तों के बारे में पढ़ें. रिमोट एक्ज़ीक्यूट करने के सेक्शन पर भी ध्यान दें, जिसके लिए कुछ और बातों की ज़रूरत होती है.
ज़रूरत के मुताबिक कई बदलाव किए जा सकते हैं, लेकिन इस दस्तावेज़ में lcov
रिपोर्ट बनाने और उनके इस्तेमाल पर ज़ोर दिया गया है. फ़िलहाल, यह रिपोर्ट बेहतर तरीके से काम करती है.
कवरेज रिपोर्ट बनाना
वीडियो की रणनीति
कवरेज रिपोर्ट बनाने के बुनियादी वर्कफ़्लो के लिए, ये शर्तें ज़रूरी हैं:
- टेस्ट टारगेट वाला बेसिक डेटा स्टोर करने की जगह
- ऐसा टूलचेन जिसमें अलग-अलग भाषा के हिसाब से कोड कवरेज टूल इंस्टॉल किए गए हैं
- सही "इंस्ट्रूमेंटेशन" कॉन्फ़िगरेशन
ये दोनों, खास तौर पर भाषा के हिसाब से हैं और काफ़ी हद तक आसान हैं. हालांकि, मुश्किल प्रोजेक्ट के लिए, दूसरा तरीका ज़्यादा मुश्किल हो सकता है.
इस मामले में "इंस्ट्रुमेंटेशन" का मतलब ऐसे कवरेज टूल से है
जिनका इस्तेमाल किसी खास टारगेट के लिए किया जाता है. Bazel, --instrumentation_filter
फ़्लैग का इस्तेमाल करके, फ़ाइलों के किसी खास सबसेट के लिए इसे चालू करने की अनुमति देता है. यह फ़्लैग की मदद से, टारगेट किए गए उन टारगेट के लिए फ़िल्टर तय किया जाता है जिनका टेस्ट डिवाइस के हिसाब से किया जाता है. जांच के लिए इंस्ट्रुमेंटेशन चालू करने के लिए, --instrument_test_targets
फ़्लैग की ज़रूरत होती है.
डिफ़ॉल्ट रूप से, bazel टारगेट पैकेज से मिलान करने की कोशिश करता है और काम के फ़िल्टर को 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 प्रोजेक्ट के रूट में लागू किया जाता है.
नतीजा देखने के लिए, genhtml
डायरेक्ट्री में बनाई गई index.html
फ़ाइल को किसी भी वेब ब्राउज़र में खोलें.
genhtml
टूल या lcov
कवरेज फ़ॉर्मैट के बारे में ज़्यादा मदद पाने और जानकारी पाने के लिए, lcov प्रोजेक्ट देखें.
रिमोट तरीके से एक्ज़ीक्यूशन
फ़िलहाल, रिमोट टेस्ट की मदद से चलाने के लिए कुछ चेतावनियां हैं:
- रिपोर्ट संयोजन कार्रवाई अभी दूर से नहीं चल सकती है. ऐसा इसलिए है, क्योंकि Bazel, कवरेज आउटपुट फ़ाइलों को अपने ग्राफ़ का हिस्सा नहीं मानता (यह समस्या देखें). इसलिए, वह उन्हें कॉम्बिनेशन ऐक्शन के इनपुट के तौर पर सही तरीके से नहीं दिखा सकता. इससे बचने के लिए,
--strategy=CoverageReport=local
का इस्तेमाल करें.- ध्यान दें: अगर Bazel को
local,remote
आज़माने के लिए सेट अप किया गया है, तो--strategy=CoverageReport=local,remote
जैसा कुछ बताना ज़रूरी हो सकता है. ऐसा इसलिए है, क्योंकि Bazel, रणनीतियों को कैसे हल करता है.
- ध्यान दें: अगर Bazel को
--remote_download_minimal
और इससे मिलते-जुलते फ़्लैग की वजह से उनका इस्तेमाल नहीं किया जा सकता.- अगर पहले से ही टेस्ट को कैश मेमोरी में सेव किया गया है, तो फ़िलहाल Bazel कवरेज की जानकारी नहीं बना पाएगा. इसे ठीक करने के लिए,
--nocache_test_results
को खास तौर पर कवरेज के लिए सेट किया जा सकता है. हालांकि, टेस्ट में लगने वाले समय के हिसाब से, इसमें बहुत ज़्यादा शुल्क देना पड़ता है. --experimental_split_coverage_postprocessing
और--experimental_fetch_all_coverage_outputs
- आम तौर पर, कवरेज, टेस्ट ऐक्शन के हिस्से के तौर पर चलाया जाता है. इसलिए, डिफ़ॉल्ट रूप से, हमें सभी कवरेज को डिफ़ॉल्ट रूप से, रिमोट एक्ज़ीक्यूशन के आउटपुट के तौर पर नहीं मिलता. ये फ़्लैग डिफ़ॉल्ट को ओवरराइड करते हैं और कवरेज डेटा लेते हैं. ज़्यादा जानकारी के लिए यह अंक देखें.
भाषा के हिसाब से कॉन्फ़िगरेशन
Java
Java को डिफ़ॉल्ट कॉन्फ़िगरेशन के साथ-साथ अलग तरीके से काम करना चाहिए. bazel टूलचेन में वे सभी चीज़ें शामिल होती हैं जो रिमोट तौर पर काम करने के लिए ज़रूरी होती हैं. इनमें JUnit शामिल है.
Python
ज़रूरी शर्तें
Python के साथ कवरेज चलाने की कुछ ज़रूरी शर्तें हैं:
- एक बेज़ल बाइनरी, जिसमें b01c859 शामिल है. यह Bazel >3.0 से ज़्यादा होना चाहिए.
- Reporting.py का बदला गया वर्शन.
संशोधित कवरेज.py का उपयोग करना
ऐसा करने के लिए, rules_python की मदद ली जा सकती है. इससे requirements.txt
फ़ाइल को इस्तेमाल किया जा सकता है. इसके बाद, फ़ाइल में बताई गई ज़रूरी शर्तों को बाज़ल टारगेट के तौर पर बनाया जाता है. इसके लिए, pip_install रिपॉज़िटरी नियम का इस्तेमाल किया जाता है.
requirements.txt
में यह एंट्री होनी चाहिए:
git+https://github.com/ulfjack/coveragepy.git@lcov-support
इसके बाद, rules_python
, pip_install
, और requirements.txt
फ़ाइल को वर्कस्पेस फ़ाइल में इस तरह इस्तेमाल किया जाना चाहिए:
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 नियम Pythontoolchain पर निर्भर करता है. इसलिए, इसका इस्तेमाल 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 Toolchain को उदाहरण के तौर पर कॉन्फ़िगर करें.
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",
)