
こんにちは。よっしーです(^^)
本日は、Go言語の.統合テストのカバレッジついて解説しています。
背景
Go言語でテストを書いていると、「go test -coverprofileでカバレッジが取れるのは知っているけど、統合テストのカバレッジってどうやって測るんだろう?」と疑問に思ったことはありませんか?
公式ドキュメントには、Go 1.20から統合テストのカバレッジ測定がサポートされたことが書かれていますが、英語で書かれている上に、ユニットテストとの違いや具体的な手順の説明が簡潔すぎて、初めて読むと「結局どうすればいいの?」と戸惑ってしまうかもしれません。
この記事では、公式ドキュメントの内容を丁寧な日本語に翻訳し、さらに初心者の方でも理解できるように、ユニットテストと統合テストの違い、なぜ3ステップ必要なのか、そして実際にどのようなコマンドを実行すればよいのかを、具体例を交えて解説していきます。
統合テストのカバレッジ測定は一見難しそうに見えますが、仕組みを理解すれば決して複雑ではありません。実際のアプリケーションでどれだけコードがテストされているかを把握することで、より品質の高いソフトウェア開発ができるようになります。一緒に学んでいきましょう!
カバレッジプロファイルレポートの作成
このセクションでは、”go tool covdata” を使用してカバレッジデータファイルから人間が読めるレポートを生成する方法について説明します。
カバーされたステートメントの割合を報告する
インストルメンテーションされた各パッケージの「カバーされたステートメントの割合」メトリックを報告するには、コマンド “go tool covdata percent -i=<directory>” を使用します。上記の実行セクションの例を使用すると:
$ ls somedata
covcounters.c6de772f99010ef5925877a7b05db4cc.2424989.1670252383678349347
covmeta.c6de772f99010ef5925877a7b05db4cc
$ go tool covdata percent -i=somedata
main coverage: 100.0% of statements
mydomain.com/greetings coverage: 100.0% of statements
$
ここでの「カバーされたステートメント」の割合は、go test -cover で報告されるものと直接対応しています。
解説
レポート生成の基本
前のセクションまでで、カバレッジデータ(バイナリファイル)を収集しました。このセクションでは、そのデータを人間が理解できる形に変換します。
料理の例え:
- カバレッジデータ = レジのデータ(機械的な記録)
- レポート生成 = 売上報告書の作成(人間が読める形式)
percent モード: カバレッジ率を表示
基本的な使い方
go tool covdata percent -i=<データディレクトリ>
具体例:
$ go tool covdata percent -i=coverage
main coverage: 85.0% of statements
mydomain.com/handlers coverage: 72.5% of statements
mydomain.com/models coverage: 90.0% of statements
出力の読み方
出力形式
<パッケージ名> coverage: <割合>% of statements
各要素の意味:
| 要素 | 説明 | 例 |
|---|---|---|
| パッケージ名 | 測定されたパッケージ | main, mydomain.com/handlers |
| coverage | カバレッジの意味 | – |
| 割合 | カバーされたコードの割合 | 85.0%, 100.0% |
| of statements | ステートメント単位での測定 | – |
ステートメント(statements)とは
ステートメントとは、プログラムの「実行可能な1つの命令」のことです。
ステートメントの例
func Add(a, b int) int {
result := a + b // ステートメント1
return result // ステートメント2
}
// この関数には2つのステートメントがある
func CheckAge(age int) string {
if age >= 20 { // ステートメント1(条件判定)
return "adult" // ステートメント2
}
return "minor" // ステートメント3
}
// この関数には3つのステートメントがある
カバレッジ率の計算方法
計算式:
カバレッジ率 = (実行されたステートメント数 / 全ステートメント数) × 100
具体例
// handlers/user.go
package handlers
func HandleUser(action string) string {
if action == "create" { // ステートメント1(常に実行)
return createUser() // ステートメント2(actionが"create"の時)
} else if action == "delete" { // ステートメント3(常に実行)
return deleteUser() // ステートメント4(actionが"delete"の時)
}
return "unknown" // ステートメント5(その他の時)
}
// 全部で5つのステートメント
テストケース1: action=”create” のみ実行
GOCOVERDIR=coverage ./myapp --action=create
- 実行されたステートメント: 1, 2, 3(3個)
- カバレッジ: 3/5 = 60%
テストケース2: action=”create” と “delete” を実行
GOCOVERDIR=coverage ./myapp --action=create
GOCOVERDIR=coverage ./myapp --action=delete
- 実行されたステートメント: 1, 2, 3, 4(4個)
- カバレッジ: 4/5 = 80%
テストケース3: すべてのパターンを実行
GOCOVERDIR=coverage ./myapp --action=create
GOCOVERDIR=coverage ./myapp --action=delete
GOCOVERDIR=coverage ./myapp --action=other
- 実行されたステートメント: 1, 2, 3, 4, 5(5個)
- カバレッジ: 5/5 = 100%
実際の例で理解する
例1: シンプルなプログラム
# プログラムの準備
$ cat main.go
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
func greet(name string) string {
return "Hello, " + name
}
# ビルド
$ go build -cover -o myapp .
# 実行
$ mkdir coverage
$ GOCOVERDIR=coverage ./myapp
# レポート生成
$ go tool covdata percent -i=coverage
main coverage: 50.0% of statements
なぜ50%なのか?
main()関数は実行されたgreet()関数は呼ばれていない- 2つの関数のうち1つしか実行されていない
例2: 複数パッケージのプログラム
# プロジェクト構成
myproject/
├── main.go
├── handlers/
│ └── api.go
└── models/
└── user.go
# ビルドと実行
$ go build -cover -o myapp .
$ GOCOVERDIR=coverage ./myapp
# レポート
$ go tool covdata percent -i=coverage
main coverage: 100.0% of statements
myproject/handlers coverage: 75.0% of statements
myproject/models coverage: 50.0% of statements
解釈:
mainパッケージ: すべてのコードが実行された(100%)handlersパッケージ: 一部のAPIハンドラーが使われていない(75%)modelsパッケージ: 半分のモデル操作しか実行されていない(50%)
go test -cover との比較
go test -cover(単体テスト)
$ go test -cover
PASS
coverage: 85.0% of statements
ok mypackage 0.123s
特徴:
- テストコード(
*_test.go)を実行 - パッケージ単位での測定
- 簡単で素早い
go tool covdata percent(統合テスト)
$ go tool covdata percent -i=coverage
main coverage: 85.0% of statements
mypackage/handlers coverage: 72.5% of statements
特徴:
- 実際のバイナリを実行
- 複数パッケージを同時に測定
- より実際の使用に近い
重要なポイント: 両方のツールは同じ計算方法を使用しているため、カバレッジの数値は直接比較できます。
実践例:Webアプリケーション
#!/bin/bash
# coverage-test.sh
# クリーンアップ
rm -rf coverage
mkdir coverage
# ビルド
echo "ビルド中..."
go build -cover -o webapp ./cmd/server
# Webサーバーを起動
echo "サーバー起動中..."
GOCOVERDIR=coverage ./webapp &
SERVER_PID=$!
# サーバーの起動を待つ
sleep 2
# 各種エンドポイントをテスト
echo "APIテスト実行中..."
curl -s http://localhost:8080/api/users > /dev/null
curl -s http://localhost:8080/api/posts > /dev/null
curl -s http://localhost:8080/health > /dev/null
# サーバー停止
echo "サーバー停止中..."
kill $SERVER_PID
wait $SERVER_PID 2>/dev/null
# カバレッジレポート生成
echo "カバレッジレポート:"
go tool covdata percent -i=coverage
実行結果の例:
ビルド中...
サーバー起動中...
APIテスト実行中...
サーバー停止中...
カバレッジレポート:
main coverage: 100.0% of statements
webapp/handlers coverage: 66.7% of statements
webapp/middleware coverage: 50.0% of statements
webapp/models coverage: 80.0% of statements
カバレッジ率の目安
| カバレッジ率 | 評価 | 説明 |
|---|---|---|
| 90-100% | 優秀 | ほぼすべてのコードがテストされている |
| 70-90% | 良好 | 主要な機能はカバーされている |
| 50-70% | 改善の余地あり | 重要な部分が抜けている可能性 |
| 50%未満 | 要改善 | 多くのコードがテストされていない |
注意点:
- 100%が必ずしも良いとは限らない
- エラーハンドリングなど、実行が難しい部分もある
- 重要なのは「重要なコードがテストされているか」
複数実行の統合例
# 異なるシナリオで実行
GOCOVERDIR=coverage ./myapp scenario1
GOCOVERDIR=coverage ./myapp scenario2
GOCOVERDIR=coverage ./myapp scenario3
# 統合されたカバレッジ率を表示
$ go tool covdata percent -i=coverage
main coverage: 95.0% of statements
仕組み:
- scenario1: 30%のコードをカバー
- scenario2: 40%のコードをカバー
- scenario3: 50%のコードをカバー
- 統合結果: 重複を除いて95%(一部が複数のシナリオで実行される)
トラブルシューティング
問題1: 0%と表示される
$ go tool covdata percent -i=coverage
main coverage: 0.0% of statements
考えられる原因:
- プログラムがすぐにクラッシュした
- メインロジックが実行されていない
- データファイルが正しく生成されていない
確認方法:
# データファイルを確認
ls -la coverage/
# プログラムが正常終了したか確認
echo $? # 0なら正常終了
問題2: パッケージが表示されない
$ go tool covdata percent -i=coverage
main coverage: 100.0% of statements
# 他のパッケージが表示されない
原因:
-coverビルド時にそのパッケージが含まれていない- そのパッケージのコードが実行されていない
解決策:
# すべてのパッケージを明示的に含める
go build -cover -coverpkg=./... -o myapp .
問題3: 複数ディレクトリの統合
# 個別に見ると
$ go tool covdata percent -i=coverage/test1
main coverage: 50.0% of statements
$ go tool covdata percent -i=coverage/test2
main coverage: 60.0% of statements
# 統合すると
$ go tool covdata percent -i=coverage/test1,coverage/test2
main coverage: 80.0% of statements # 単純な足し算ではない
理由: 重複する部分があるため、単純に足し算にはならない。
実用的なスクリプト
#!/bin/bash
# full-coverage-report.sh
# 設定
APP="./myapp"
COVERAGE_DIR="coverage"
# 初期化
rm -rf $COVERAGE_DIR
mkdir $COVERAGE_DIR
# ビルド
echo "=== ビルド ==="
go build -cover -o $APP .
# 複数シナリオを実行
scenarios=("basic" "advanced" "error-cases")
for scenario in "${scenarios[@]}"; do
echo "=== シナリオ: $scenario ==="
GOCOVERDIR=$COVERAGE_DIR $APP --test=$scenario
done
# 総合レポート
echo ""
echo "=== 総合カバレッジレポート ==="
go tool covdata percent -i=$COVERAGE_DIR
# パッケージごとの詳細が必要な場合の判定
echo ""
read -p "詳細レポートを表示しますか? (y/n) " answer
if [ "$answer" = "y" ]; then
go tool covdata func -i=$COVERAGE_DIR
fi
まとめ
| 項目 | 説明 |
|---|---|
| コマンド | go tool covdata percent -i=<dir> |
| 出力 | パッケージごとのカバレッジ率 |
| 単位 | ステートメント(実行可能な命令) |
| 計算 | (実行されたステートメント / 全ステートメント) × 100 |
| go test | 同じ計算方法で互換性あり |
重要なポイント:
percentモードで素早くカバレッジ率を確認- パッケージごとの数値が一目でわかる
go test -coverと同じ計算方法- 複数回の実行結果が自動的に統合される
次の記事では、より詳細なレポート(関数ごとのカバレッジなど)の生成方法を見ていきます。
おわりに
本日は、Go言語の統合テストのカバレッジについて解説しました。

何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。
それでは、また明日お会いしましょう(^^)

コメント