LASSIC Media らしくメディア
テストカバレッジ計測とゲート導入を外注する要点
LASSIC IT事業部|元請(プライムベンダー)としてシステム保守・運用を受託
この記事のポイント
- テストカバレッジには行・分岐・関数といった種類があり、言語ごとに計測ツールが異なります。
- カバレッジの数値を上げること自体は目的ではなく、未テスト箇所を見つける手がかりとして使う視点が欠かせません。
- カバレッジゲートは既存コード全体を対象にせず、新規コードの差分に基準を絞ることで運用が続きやすくなります。
目次
テストカバレッジの種類と言語別ツールの違い
テストカバレッジ計測とは、自動テストを実行した際にソースコードのどの部分が実際に通過したかを数値化する手法です。カバレッジには複数の種類があり、同じ「カバレッジ80%」という数値でも、何を分母にしているかで意味が変わります。
テストカバレッジ計測とは、自動テストの実行時にコードのどの行・分岐が通過したかを可視化し、未テスト箇所を洗い出すための計測手法を指します*1。カバレッジの種類として代表的なのは行カバレッジ・分岐カバレッジ・関数カバレッジの3つです。
行カバレッジは、ソースコードの各行が一度でも実行されたかを計測します。分岐カバレッジは、if文やswitch文などの条件分岐について、条件が真になる経路と偽になる経路の両方が実行されたかを見ます。Python向けのカバレッジ計測ツールcoverage.pyの公式ドキュメント*2は、行カバレッジでは「if文が真の場合しか実行しなくても全行通過扱いになる」一方、分岐カバレッジは「if文が偽になる経路が未実行であること」を検出できると説明しています。関数カバレッジは、定義された関数のうち何個が一度でも呼び出されたかを示す指標です。
計測ツールは言語ごとに異なります。Java向けのJaCoCo公式ドキュメント*3は、命令カバレッジ・分岐カバレッジ・サイクロマティック複雑度・行カバレッジ・メソッド/クラスカバレッジという複数のメトリクスを提供すると説明しています。Go言語では標準ツールチェーンに含まれるgo test -coverが使われ、Go公式ブログ*4によると、ソースコードに計測用の処理を挿入する方式でブロック単位の実行状況を記録します。JavaScript/TypeScript領域ではIstanbul系のnycやJestの内蔵カバレッジ機能、Python領域では前述のcoverage.pyが広く使われています。
外注や社内標準化を検討する際は、まず対象プロジェクトの言語・フレームワークに対応したツールを確認し、行カバレッジだけでなく分岐カバレッジまで計測できるかを基準の一つにする進め方が現実的です。
カバレッジの数値が高くても品質を保証しない理由
テストカバレッジの数値を高めること自体を目標にすると、かえってテストの質が落ちる場合があります。ソフトウェア設計に関する発信で知られるMartin Fowler氏は、自身のブログ記事「TestCoverage」*1で、カバレッジの数値を満たすためだけにテストを書き、実際に何を検証しているかを考えていないケースがあると指摘しています。
同記事は、カバレッジ分析の本来の価値を「テストされていないコード箇所を見つけるためのツール」として位置づけています。数値そのものを成果指標にするのではなく、定期的にカバレッジを計測し、未テストの箇所が本当に問題かどうかを検討する使い方を勧めている点が要旨です。目安として、思慮深いテストを実施しているプロジェクトでは80〜90%台のカバレッジになりやすく、50%を下回ると注意信号だと述べる一方、数値だけでテストの十分性は判断できないとしています。
数値を追い求めることで生じる典型的な問題が、アサーション(検証条件)を伴わないテストです。関数を呼び出す行だけを実行してカバレッジ上は「通過」としながら、戻り値や例外の発生を何も検証しないテストを書けば、カバレッジの数値は上がっても不具合の検出力は上がりません。カバレッジはコードが実行されたかどうかを示す指標であり、その実行結果が正しいかどうかまでは判定しないためです。
全網羅を目指す運用にも注意が必要です。分岐が複雑な例外処理や、外部サービス障害時のみ通る異常系コードまで数値上の対象に含めると、テストを書く労力に対して得られる不具合検出の効果が見合わない場合があります。カバレッジは品質を測る単一の指標ではなく、テストが薄い箇所を見つけるための手がかりの一つとして扱う視点が実務では重要です。
新規コードに絞るdiffカバレッジという考え方
既存プロジェクトにカバレッジ計測を導入する際、プロジェクト全体のカバレッジを一気に引き上げようとすると現実的ではありません。長年運用されてきたコードベースには、テストが整備されていない既存コードが相当量残っているためです。ここで有効な考え方が、新規に追加・変更した行だけを対象にする「diffカバレッジ」(差分カバレッジ、パッチカバレッジとも呼ばれる)です。
カバレッジ計測サービスのCodecov公式ドキュメント*5は、プルリクエスト単位で計測する「パッチステータス」について、「プルリクエストで変更された行、またはプルリクエストにないコミットの場合は単一コミットの変更行のみを計測する」と説明しています。プロジェクト全体のカバレッジが低い水準であっても、新規に追加した行のテストが不足していれば、そのプルリクエストのパッチカバレッジは低く表示される仕組みです。
この考え方の利点は、既存コードのテスト不足を理由に新規開発が止まらない点にあります。プロジェクト全体のカバレッジ基準をいきなり適用すると、既存コードの改修だけで基準未達になり、開発チームの手が止まりかねません。新規コードの差分だけを基準にすれば、これから書くコードにテストを伴わせる運用を、既存資産の整備状況に左右されずに始められます。
一方で、diffカバレッジだけに頼ると、既存コードのテスト不足がいつまでも解消されないという課題も残ります。実務では、新規コードの基準を先に運用に乗せたうえで、重要度の高い既存モジュールから順にテストを追加していく段階的な計画を組み合わせる進め方が現実的です。
カバレッジゲートをCIへ段階導入する設計
カバレッジゲートとは、CI(継続的インテグレーション)のパイプライン上でカバレッジの基準を満たさない変更のマージを止める仕組みです。Codecovの公式ドキュメント*5は、プロジェクトのステータスチェックで最小カバレッジ比率を示す「target」や、カバレッジの低下許容幅を示す「threshold」といった設定項目を用意していると説明しています。
カバレッジゲートを導入する際にまず起こりやすい失敗が、初回導入時にプロジェクト全体の基準値をいきなり高く設定することです。既存コードのカバレッジが低いまま高い基準を課すと、ほとんどのプルリクエストが基準未達でブロックされ、開発チームがゲート自体を無効化する運用に流れかねません。
段階導入の設計としては、まず基準を設けずにカバレッジの数値だけを可視化する期間を設け、現状のプロジェクト全体のカバレッジ水準を把握します。次に、新規コード(diffカバレッジ)を対象にした基準をCIに組み込み、これから追加するコードにはテストを伴わせる運用を先に定着させます。既存コード全体への基準適用は、チームの運用が安定した後の段階に位置づけるという順序です。
あわせて、カバレッジの低下許容幅(threshold)を最初はやや緩めに設定し、運用に慣れるにつれて厳格化していく調整も有効です。基準を一度に厳しくしすぎると、テストの質を高める工夫ではなく、基準を通過するためだけの形式的なテストが増えるおそれがあります。カバレッジゲートは導入して終わりではなく、チームの状況に応じて基準値を見直し続ける運用が前提になります。
外注の委託範囲と発注側が準備する情報
テストカバレッジ計測とカバレッジゲートの導入を外部パートナーに委託する場合、委託範囲は初期構築と継続運用の2段階に分けて整理すると発注しやすくなります。初期構築では、対象言語に応じたカバレッジ計測ツールの選定、CI/CDパイプラインへの組込み、diffカバレッジを軸にしたゲート条件の設計を行います。
この初期構築を内製で行う場合、対象言語ごとのカバレッジツールの特性の把握、既存コードベースの現状カバレッジの調査、CI/CDパイプラインの設定変更という複数分野の知識が必要になります。特に、新規コード基準と全体基準のどちらから運用を始めるかという設計判断には、複数プロジェクトでの導入経験が影響しやすい部分です。
継続運用では、カバレッジ基準値の見直し、除外設定(自動生成コードやテスト対象外ファイルの扱い)の調整、レポートの可読性向上といった作業が発生します。カバレッジゲートは一度設定した基準を固定するものではなく、プロジェクトの成長に合わせて基準を段階的に引き上げていく運用が前提です。導入直後に基準を厳格化しすぎると、形式的なテストが増える結果につながりかねないため、運用開始後の調整を担う体制をあらかじめ確保しておくことが望まれます。
発注側が事前に準備しておく情報としては、対象リポジトリの言語・フレームワークの一覧、既存のCI/CD環境の構成、現在のテスト自動化の実施状況、カバレッジ計測をまだ行っていない場合はその理由(工数不足なのか、ツール未選定なのか)が挙げられます。これらの情報が整理されているほど、ツール選定とゲート設計を短い期間で進めやすくなります。
LASSICは、システム開発の受託・保守運用を通じて、CI/CDパイプラインの構築やテスト自動化の整備に携わってきました。カバレッジ計測ツールの選定からゲート設計、運用開始後の基準見直しまで、開発チームの体制に合わせた導入を支援する体制を整えています。
まとめ:カバレッジ計測とゲート導入を外注で進める3つの判断軸
本稿では、テストカバレッジの計測とカバレッジゲート導入について整理しました。要点を3つに集約すると次の通りです。第一に、カバレッジには行・分岐・関数といった種類があり、対象言語に応じた計測ツールを選ぶ必要があります。第二に、カバレッジの数値を上げること自体を目的にせず、未テスト箇所を見つける手がかりとして使う視点が欠かせません。第三に、カバレッジゲートは新規コードの差分(diffカバレッジ)に基準を絞って段階的に導入し、既存コード全体への適用は運用が安定した後に進めることで、開発を止めずに定着させやすくなります。外注時は、初期構築(ツール選定・CI組込み・ゲート設計)と継続運用(基準見直し)を分けて委託範囲を定義することが、導入を円滑に進める前提になります。
よくある質問
カバレッジは何%を目指せばよいですか。
一律の目標値を示すことはできません。Martin Fowler氏のブログ記事*1は、思慮深いテストを実施しているプロジェクトでは80〜90%台になりやすく、50%を下回ると注意信号だとしつつも、数値だけでテストの十分性は判断できないと述べています。数値そのものより、重要な機能や条件分岐がテストで検証されているかを優先して確認する進め方が現実的です。
行カバレッジと分岐カバレッジのどちらを計測すべきですか。
可能であれば両方を計測することが望ましいです。行カバレッジは各行が実行されたかを示しますが、条件分岐の一方の経路しか実行していなくても数値上は通過扱いになる場合があります。分岐カバレッジは条件が真・偽どちらの経路も実行されたかを検出できるため、条件分岐が多いコードほど分岐カバレッジの計測が有効です。
既存プロジェクトにカバレッジゲートを後から導入できますか。
導入できます。本文で触れた新規コードの差分(diffカバレッジ)に基準を絞る方法が、既存プロジェクトへの導入で特に有効です。既存コード全体への基準をいきなり課すのではなく、これから追加・修正するコードにテストを伴わせる運用から始めることで、通常の開発を止めずに導入を進められます。
カバレッジ計測ツールは言語ごとに何を使えばよいですか。
対象言語によって代表的なツールが異なります。Javaでは命令・分岐・行など複数のメトリクスを提供するJaCoCo*3、Go言語では標準ツールチェーンに含まれるgo test -cover*4、Python領域では分岐カバレッジにも対応するcoverage.py*2が広く使われています。JavaScript/TypeScript領域ではIstanbul系のツールやテストフレームワーク内蔵の機能が利用されます。
カバレッジゲートの基準はどのくらいの頻度で見直しが必要ですか。
運用開始直後は基準が厳しすぎたり緩すぎたりする調整が必要になりやすく、短い間隔での見直しを想定しておくことが望まれます。運用が安定した後も、新規コード基準から全体基準への移行や、除外設定の見直しなど、プロジェクトの状況に応じた継続的な調整が前提です。導入時に一度設定すれば完成する仕組みではありません。
著者:テレリモ総研編集部 鈴木 亮佑
ご不明な点はお問い合わせフォームからもご連絡いただけます。
- *1 出典:Martin Fowler「TestCoverage」(2012年)(https://martinfowler.com/bliki/TestCoverage.html)
- *2 出典:coverage.py公式ドキュメント「Branch coverage measurement」(https://coverage.readthedocs.io/en/latest/branch.html)
- *3 出典:JaCoCo公式ドキュメント「Coverage Counters」(https://www.jacoco.org/jacoco/trunk/doc/counters.html)
- *4 出典:Rob Pike「The cover story」Go公式ブログ(2013年)(https://go.dev/blog/cover)
- *5 出典:Codecov公式ドキュメント「Commit status」(https://docs.codecov.com/docs/commit-status)