Code Coverage(コードカバレッジ)は、テスト中にアプリケーションのソースコードの何パーセントが実行されるかを示すメトリクスです。テストの品質を判断し、未確認の領域を特定し、新しいテストの作成を優先順位付けするのに役立ちます。Atlassian、2025によると、最適なカバレッジレベルは70~80%です。このしきい値を超えると、テストのコストがメリットを上回り始めます。
重要なポイント
Code Coverage(コードカバレッジ)は、テスト中にアプリケーションのソースコードのどの部分が実行されたかを判断する定量的なメトリクスです。パーセンテージで表され、実行されたライン/ブランチの総数に対する比率として計算されます。高いカバレッジはバグがないことを保証するものではありませんが、見逃されたエラーのリスクを減らします。
コードカバレッジはチームが以下を行うのに役立ちます:コードの未テスト領域を見つける、テスト作成の優先順位について決定を下す、CI/CDでのテスト品質の推移を追跡する。モバイル開発では、カバレッジは特にビジネスロジック、データモデル、リポジトリにとって重要です。これらはエラーが発生する可能性が最も高いレイヤーです。
一般的な誤解:「100%のカバレッジ=完璧な品質」。実際には、100%のカバレッジは非常にまれであり、表面的なテストを犠牲にして達成されることがよくあります。効果的なカバレッジはパーセンテージの追求ではなく、クリティカルパスと境界条件の戦略的なカバレッジです。カバレッジはテスト自体の品質については何も語りません。テストはパスしても、結果の正確性を検証していない可能性があります。
Code Coverageにはいくつかのメトリクスが存在し、それぞれテストの異なる側面を測定します。Line coverage(ラインカバレッジ)は最もシンプルなメトリクスで、実行されたコード行の割合を示します。Branch coverage(ブランチカバレッジ)は、どのif-elseおよびswitchブランチがテストされたかを測定します。
Line coverageは、各ソースコード行を実行されたかどうかとしてカウントします。行に条件演算子やループが含まれている場合、制御がその行に到達していれば、すべてのブランチが処理されていなくても、その行は実行されたと見なされます。これは最も厳格でないメトリクスですが、視覚的な評価には最もわかりやすいものです。
Branch coverageは、コード内のすべての可能なブランチがテストされたかどうかを評価します。各if-elseについて、trueとfalseの両方のブランチが考慮されます。switchについては、各caseが考慮されます。Branch coverageはline coverageよりも厳格なメトリクスと見なされ、テストされていないシナリオをより頻繁に明らかにします。
| メトリクス | 測定内容 | 達成難易度 |
|---|---|---|
| Line | 実行されたコード行の割合 | 低い |
| Branch | 実行されたブランチの割合(if/else, switch) | 中程度 |
| Function | 呼び出された関数とメソッドの割合 | 低い |
| Condition | 論理サブ式の割合(&&, ||) | 高い |
Path coverageは最も厳格なメトリクスであり、関数内のすべての可能なブランチの組み合わせの検証を必要とします。実際には、path coverageは組み合わせの数が指数関数的に増加するため、ほとんど使用されません。10個のブランチを持つ関数には1024の可能なパスがあります。
モバイル開発では、プラットフォームに応じてCode Coverageを測定するためにさまざまなツールが使用されます。Androidの標準はJaCoCo(Java Code Coverage)で、Gradleと統合し、単体テストとインスツルメンテーションテストの両方をサポートします。iOSでは、Xcodeに組み込まれたXCCovが使用されます。
JaCoCoはHTML、XML、CSV形式でレポートを生成します。HTMLレポートは行を視覚的に強調表示します。緑色は実行済み、赤色は未実行、黄色は部分的に実行済みです。XMLレポートはSonarQubeやその他のコード分析システムと互換性があります。JaCoCoはクラスのフィルタリングをサポートしており、生成されたコード、データバインディング、BuildConfigを除外できます。
// build.gradle — JaCoCo設定
android {
buildTypes {
debug {
testCoverageEnabled = true
}
}
}
// JaCoCoレポートの生成
task jacocoTestReport(type: JacocoReport) {
dependsOn 'testDebugUnitTest'
reports {
xml.enabled = true
html.enabled = true
}
}
XCCovはコードカバレッジを測定するためのXcodeに組み込まれたツールです。テストスキームのGather coverage dataを介して有効になります。XCCovはSwiftとObjective-Cのカバレッジをサポートし、.xccovreport形式でレポートを生成し、xcodebuild -enableCodeCoverage YESを介してCIと統合します。データはコンソールに出力され、JSONでエクスポートできます。
集中型のカバレッジ監視には、SonarQube(コード品質分析+カバレッジ)、Codecov、Coverallsなどのプラットフォームが使用されます。これらのサービスはJaCoCoとXCCovからデータを集約し、トレンド、クオリティゲート、PRコメントによるGitHub/GitLabとの統合を表示します。
Code Coverageの向上には体系的なアプローチが必要です:「パーセンテージを上げる」ではなく、リスクをカバーすることです。最初のステップは、JaCoCoまたはXCCovレポートを分析し、赤色(未カバー)のクラスを特定することです。優先順位:ビジネスロジック→リポジトリ→ViewModel→UIコンポーネント。
テスト駆動開発(TDD)は、実装前にテストを作成するため、自動的に高いカバレッジを確保します。プロセス:赤(失敗するテストを書く)→緑(最小限のコードを書く)→リファクタリング。TDDは開発者を訓練し、しばしばテストされないままになる境界ケースや例外的な状況をカバーするように強制します。
1つのパラメータ化テストは、数十の通常のテストを置き換えます。JUnitとXCTestはパラメータ化をサポートしています:JUnit 5の@ParameterizedTest、XCTestのtestPerformanceExampleを使用したXCTestCase。パラメータ化を使用すると、コードの重複なしに複数の入力データを検証でき、ブランチと条件のカバレッジを大幅に拡大します。
// KotlinでのJUnit 5を使用したパラメータ化テスト
@ParameterizedTest
@ValueSource(strings = ["user@test.com", "admin@test.com", "test@example.com"])
fun `validate email returns true for valid addresses`(email: String) {
val result = EmailValidator.isValid(email)
Assertions.assertTrue(result)
}
最も一般的な間違いは、テストの品質を分析せずにパーセンテージを追求することです。チームはテストのためにテストを書き始めます:getterやsetterをチェックし、異なるレベルでカバレッジを重複させ、些細なメソッドをテストします。これにより高いパーセンテージが得られますが、実際の品質は向上しません。
高いCode Coverageは、アプリケーションが十分にテストされているという誤った感覚を生み出す可能性があります。テストはコード行を実行しても、結果の正確性を検証しない場合があります。例:テストが割引計算メソッドを呼び出しても、金額をチェックしない場合、行は実行され、カバレッジは増加しますが、バグは見つかりません。
典型的な間違いは、「ハッピーパス」のみをテストし、境界ケース(空のリスト、null値、最大数、不正な形式)を無視することです。ほとんどのバグは境界と例外で発生します。Branch coverageは見逃されたブランチを特定するのに役立ちますが、境界値の検証を保証するものではありません。
ミューテーションテストは、ソースコードにミューテーション(人工的なエラー)を導入し、テストが失敗するかどうかを確認するテスト品質評価方法です。PitestはJavaとKotlin向けの人気のあるミューテーションテストツールです。ミューテーションでテストが失敗しない場合、その条件を検証していないことを意味します。
Pitestはミュータントを作成します。これは、例えば>が>=に、trueがfalseに置き換えられた、またはメソッド呼び出しが削除されたソースコードの修正コピーです。次に、各ミュータントに対してテストが実行されます。テストがパスした場合、ミュータントは生存したことになり、テストがそのシナリオをカバーしていないことを意味します。テストが失敗した場合、ミュータントは殺され、テストは有効です。
// build.gradle — Pitest設定
plugins {
id 'info.solidsoft.pitest' version '1.15.0'
}
pitest {
targetClasses = ['com.example.app.*']
targetTests = ['com.example.app.*Test']
threads = 4
outputFormats = ['HTML', 'XML']
mutationThreshold = 80
coverageThreshold = 85
}
Pitestは多くのタイプのミューテーションをサポートしています:条件演算子の変更(== → !=, < → <=)、メソッド呼び出しの削除、戻り値の置換(true → false)、算術演算の変更(+ → -)、インクリメントのミューテーション(i++ → i--)。より多くの種類のミューテーションがテストによって殺されるほど、テストスイートはより信頼性が高くなります。
目標のミューテーションスコアは80%以上です。これは、人工的なエラーの80%がテストによって検出されることを意味します。90%のコードカバレッジはテストがバグを見つけることを保証しません。ミューテーションテストはより客観的な評価を提供します。PitestはクオリティゲートとしてCIに統合でき、ミューテーションスコアがしきい値を下回った場合にビルドをブロックします。
CI/CDでのCode Coverageの自動制御には、クオリティゲートが使用されます。これは、違反した場合にビルドを不安定としてマークするか拒否するしきい値です。SonarQubeでは、メトリクスの組み合わせ(カバレッジ(≥80%)、バグの数、脆弱性、重複コード)に基づいてクオリティゲートを設定できます。
GitHub Actionsでは、Code Coverageはアクションステップ(カバレッジ付きでテストを実行→Codecovにレポートをアップロード→しきい値をチェック)を通じて統合されます。Codecovは自動的にPRにカバレッジの差分をコメントし、どの行が変更され、それが全体のパーセンテージにどのように影響したかを示します。カバレッジが低下した場合、追加のテストが作成されるまでPRはブロックされます。
# GitHub Actions — Codecovへのカバレッジアップロード
- name: Run Tests with Coverage
run: ./gradlew testDebugUnitTest jacocoTestReport
- name: Upload to Codecov
uses: codecov/codecov-action@v4
with:
files: ./app/build/reports/jacoco/jacocoTestReport.xml
flags: unittests
fail_ci_if_error: true
- name: Check Coverage Threshold
run: |
coverage=$(grep -oP 'branchCoverage="\K[0-9.]+' report.xml)
if (( $(echo "$coverage < 80" | bc -l) )); then
echo "Coverage $coverage% is below 80% threshold"
exit 1
fi
JaCoCoとXCCovのHTMLレポートには、カバレッジの視覚的な強調表示が含まれています。緑色は実行済み行、赤色は未実行です。SonarQubeはさらに、ファイル、クラス、メソッド、行レベルでのカバレッジ、およびスプリントごとのカバレッジ変更の履歴を表示します。これは、リファクタリングやテスト追加に関する決定を下すのに役立ちます。
よくある質問
モバイルプロジェクトでは、ビジネスロジックで70~80%、UIコンポーネントで50~60%のカバレッジが良いとされています。80%を超えると、テストコストがメリットを上回り始めます。パーセンテージは目標ではなく指標であり、モジュールごとに目標レベルが異なる場合があることを覚えておくことが重要です。
Line Coverageは実行されたコード行の数を示します。Branch Coverageはテストされた分岐数(if-else、switch)を示します。ifを含む行は実行されても、trueブランチのみがテストされ、falseがテストされていない可能性があります。Branch Coverageの方が厳格で、より多くの見逃されたシナリオを明らかにします。
CI/CDでは、カバレッジはクオリティゲートを介して統合されます。カバレッジがしきい値を下回るとビルドがブロックされます。AndroidではJaCoCo + SonarQubeが使用され、iOSではxcodebuild -enableCodeCoverageと.xccovreportの解析が使用されます。GitHub ActionsにはCodecov用の既製のアクションがあります。
はい、JaCoCoは標準のJVMカバレッジメカニズムを介してJetpack Composeをサポートしています。ただし、Composeコードには、JaCoCoが完全にカバーできない可能性のある生成されたラムダ式が多数含まれています。フィルターを使用して、生成されたComposeコードをレポートから除外することをお勧めします。
誤ったカバレッジは、テストがコードを実行しても結果を検証しない場合に発生します。解決策:重要なシナリオごとにアサーションチェックを記述し、ミューテーションテスト(Pitest)を使用してテスト品質を検証し、パーセンテージだけでなくどのブランチがカバーされているかを分析します。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。