Bazel によるコード カバレッジ

Bazel には、bazel coverage でテストできるリポジトリに関するコード カバレッジ レポートを生成する coverage サブコマンドがあります。さまざまな言語のエコシステムには共通性があるため、特定のプロジェクトでこの作業を行うのは必ずしも容易ではありません。

このページでは、カバレッジ レポートを作成および表示するための一般的なプロセスについて説明します。また、設定がよく知られている言語固有の注意事項も示します。まず一般的なセクションを読み、次に特定の言語の要件を読むことをおすすめします。リモート実行セクションにも注記します。追加の考慮事項がいくつかあります。

さまざまなカスタマイズが可能ですが、このドキュメントでは、現時点では最も適切にサポートされている lcov レポートの作成と使用を中心に説明します。

カバレッジ レポートの作成

準備

カバレッジ レポートの基本的なワークフローは次のとおりです。

  • テスト ターゲットを含む基本的なリポジトリ
  • 言語固有のコード カバレッジ ツールがインストールされたツールチェーン
  • 適切な「インストゥルメンテーション」構成

最初の 2 つは言語固有であり、ほぼ単純ですが、後者のプロジェクトは複雑なプロジェクトでは難しい場合があります。

ここでの「インストルメンテーション」とは、特定のターゲットに使用されるカバレッジ ツールを指します。Bazel は、--instrumentation_filter フラグを使用して、特定のファイルのサブセットに対してこれを有効にできます。このフラグは、インストルメンテーションでテストされるターゲットのフィルタを指定します有効。テスト用のインストルメンテーションを有効にするには、--instrument_test_targets フラグが必要です。

デフォルトでは、bazel はターゲット パッケージのマッチングを試み、関連するフィルタを INFO メッセージとして出力します。

実行中のカバレッジ

カバレッジ レポートを作成するには、bazel coverage --combined_report=lcov [target] を使用します。これにより、ターゲットのテストが実行され、各ファイルの lcov 形式のカバレッジ レポートが生成されます。

完了後、バゼルは、生成されたすべてのカバレッジ ファイルを収集して 1 つにマージするアクションを実行し、最終的に $(bazel info output_path)/_coverage/_coverage_report.dat の下に作成されます。

テストが不合格の場合にもカバレッジ レポートが作成されますが、不合格になったテストには適用されず、合格したテストのみが報告されます。

カバレッジの確認

カバレッジ レポートは、人間が判読できない lcov 形式でのみ出力されます。ここから、genhtml ユーティリティ(lcov プロジェクトの一部)を使用して、ウェブブラウザで表示可能なレポートを生成できます。

genhtml --output genhtml "$(bazel info output_path)/_coverage/_coverage_report.dat"

genhtml はソースコードも読み取り、これらのファイルに不足しているカバレッジにアノテーションを付けることに注意してください。そのためには、bazel プロジェクトのルートで genhtml を実行する必要があります。

結果を表示するには、genhtml ディレクトリで生成された index.html ファイルをウェブブラウザで開きます。

genhtml ツールまたは lcov カバレッジ形式の詳細については、lcov プロジェクトをご覧ください。

リモート実行

リモートテストの実行に関する注意点は次のとおりです。

  • レポートの組み合わせの操作は、現時点ではリモートから実行できません。これは、Bazel がカバレッジ出力ファイルをグラフの一部として考慮せず(この問題を参照)、組み合わせへの入力として正しく処理できないためです。アクション この問題を回避するには、--strategy=CoverageReport=local を使用します。
    • 注: Bazel が local,remote を試すように設定されている場合、Bazel が戦略を解決する仕組みにより、--strategy=CoverageReport=local,remote などを指定する必要があります。
  • 前者の結果として、--remote_download_minimal などのフラグも使用できません。
  • 現在、テストがキャッシュに保存されている場合、Bazel はカバレッジ情報の作成に失敗します。この問題を回避するには、--nocache_test_results をカバレッジ実行専用に設定できますが、テストに多大なコストがかかります。
  • --experimental_split_coverage_postprocessing--experimental_fetch_all_coverage_outputs
    • 通常、カバレッジはテスト アクションの一部として実行されるため、デフォルトではすべてのカバレッジがリモート実行の出力として返されるわけではありません。これらのフラグはデフォルト値をオーバーライドし、カバレッジ データを取得します。詳しくは、この問題をご覧ください。

言語固有の構成

Java

Java は、デフォルト設定のまますぐに使用できます。bazel ツールチェーンには JUnit を含め、リモート実行に必要なすべての機能が含まれています。

Python

前提条件

Python でカバレッジを実行するには、いくつかの前提条件があります。

変更後の Coverage.py を使用する場合

これを行うには rules_python を使用します。これにより、requirements.txt ファイルを使用できるようになります。ファイル内にリストされている要件は、{ を使用して bazel ターゲットとして作成されます。 101}pip_install リポジトリ ルールがあります。

requirements.txt に次のエントリが含まれているはずです。

git+https://github.com/ulfjack/coveragepy.git@lcov-support

次に、rules_pythonpip_installrequirements.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",
    ],
)