نسبة استخدام رموز الصفحة مع Bazel

يقدّم Bazel أمرًا فرعيًا بعنوان coverage لإنشاء تقارير تغطية الرمز في المستودعات التي يمكن اختبارها باستخدام bazel coverage. ونظرًا للخصوصيات المميّزة للمنظومة المتكاملة المتنوعة للغات، لا يُعتبر من السهل تنفيذ هذا العمل في مشروع معيّن.

توثّق هذه الصفحة العملية العامة لإنشاء تقارير التغطية وعرضها، كما تعرض بعض الملاحظات بلغات معيّنة للغات التي تكون إعداداتها معروفة. ومن الأفضل قراءة القسم العام أولاً، ثم القراءة عن متطلبات لغة معيّنة. لاحظ أيضًا قسم التنفيذ عن بُعد الذي يتطلب بعض الاعتبارات الإضافية.

على الرغم من إمكانية إجراء الكثير من عمليات التخصيص، يركّز هذا المستند على إنشاء تقارير lcov واستخدامها، وهو حاليًا المسار الأكثر توافقًا.

إنشاء تقرير تغطية

الإعداد

يتطلب سير العمل الأساسي لإنشاء تقارير التغطية ما يلي:

  • مستودع أساسي باستهدافات الاختبار
  • سلسلة أدوات تم تثبيت أدوات تغطية اللغة بها
  • ضبط "طريقة قياس&صحيح" صحيحة

والإعدادان السابقان يتكلمان لغة خاصة وبسيطة في الغالب، إلا أن النوع الثاني قد يكون أكثر صعوبة عند تنفيذ المشاريع المعقدة.

"الحاسبة&quot؛ تشير في هذه الحالة إلى أدوات التغطية التي يتم استخدامها لهدف محدّد. ويسمح Bazel بتفعيل هذا الإعداد لمجموعة فرعية معيّنة من الملفات باستخدام العلامة --instrumentation_filter، التي تحدّد فلترًا للأهداف التي يتم اختبارها مع تفعيل الإعداد. لتفعيل قياس حالة الاختبارات، يجب استخدام علامة --instrument_test_targets.

وفقًا للإعدادات التلقائية، يحاول Bazel مطابقة الحزمة(الحزم) المستهدَفة ويطبع الفلتر ذي الصلة كرسالة 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 في جذر مشروع البازل.

لعرض النتيجة، ما عليك سوى فتح ملف 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
    • وعادةً ما يتم تشغيل التغطية كجزء من إجراء الاختبار، وبالتالي لا يتم توفير التغطية الكاملة تلقائيًا كإخراج من التنفيذ البعيد عن بُعد. تلغي هذه العلامات الإعدادات التلقائية وتحصل على بيانات التغطية. يمكنك الاطّلاع على هذه المشكلة للحصول على مزيد من التفاصيل.

الإعدادات الخاصة باللغة

Java

من المفترض أن تعمل Java تلقائيًا باستخدام الإعدادات التلقائية. تحتوي سلاسل أدوات البازار على كل ما هو ضروري للتنفيذ عن بُعد أيضًا، بما في ذلك JUnit.

Python

المتطلبات الأساسية

هناك بعض المتطلبات الأساسية لتشغيل التغطية باستخدام python:

استهلاك التغطية المعدّلة

لإجراء ذلك، يمكنك تنفيذ ذلك من خلال Rule_python، ما يوفّر إمكانية استخدام ملف requirements.txt، ويتم بعد ذلك إنشاء المتطلبات المذكورة في الملف كأهداف bazel باستخدام قاعدة المستودع 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",
)

ويمكن بعد ذلك استهلاك متطلبات التغطية.py من خلال أهداف الاختبار عن طريق إعداد ما يلي في ملفات 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",
    ],
)

إذا كنت تستخدم سلسلة أدوات Python مزخرفة، بدلاً من إضافة اعتمادية التغطية إلى كل هدف py_test، يمكنك إضافة أداة التغطية إلى ضبط سلسلة الأدوات.

ونظرًا لأن قاعدة pip_install تعتمد على سلسلة أدوات Python، لا يمكن استخدامها لجلب وحدة 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",
)