
こんにちは。よっしーです(^^)
本日は、Go言語の.統合テストのカバレッジついて解説しています。
背景
Go言語でテストを書いていると、「go test -coverprofileでカバレッジが取れるのは知っているけど、統合テストのカバレッジってどうやって測るんだろう?」と疑問に思ったことはありませんか?
公式ドキュメントには、Go 1.20から統合テストのカバレッジ測定がサポートされたことが書かれていますが、英語で書かれている上に、ユニットテストとの違いや具体的な手順の説明が簡潔すぎて、初めて読むと「結局どうすればいいの?」と戸惑ってしまうかもしれません。
この記事では、公式ドキュメントの内容を丁寧な日本語に翻訳し、さらに初心者の方でも理解できるように、ユニットテストと統合テストの違い、なぜ3ステップ必要なのか、そして実際にどのようなコマンドを実行すればよいのかを、具体例を交えて解説していきます。
統合テストのカバレッジ測定は一見難しそうに見えますが、仕組みを理解すれば決して複雑ではありません。実際のアプリケーションでどれだけコードがテストされているかを把握することで、より品質の高いソフトウェア開発ができるようになります。一緒に学んでいきましょう!
GO111MODULE=offモードでgo build -coverを使用できますか?
はい、go build -coverはGO111MODULE=offでも動作します。GO111MODULE=offモードでプログラムをビルドする場合、コマンドライン上でターゲットとして特に指定されたパッケージのみがプロファイリング用にインストルメンテーションされます。プロファイルに追加のパッケージを含めるには、-coverpkgフラグを使用してください。
解説
GO111MODULEとは何か
Goのモジュールシステムの歴史
GO111MODULEは、Goのモジュールシステムの動作を制御する環境変数です。
| モード | 説明 | 使用時期 |
|---|---|---|
GO111MODULE=on | モジュールモード(推奨) | Go 1.16以降のデフォルト |
GO111MODULE=off | レガシーGOPATHモード | 古いプロジェクト |
GO111MODULE=auto | 自動判定 | Go 1.11-1.15のデフォルト |
学校の例え:
- モジュールモード(on) = 新しい教育システム(推奨)
- GOPATHモード(off) = 古い教育システム(まだ動くが非推奨)
モジュールモードとGOPATHモードの違い
モジュールモード(GO111MODULE=on)- 推奨
# 現代的なプロジェクト構造
myproject/
├── go.mod # 依存関係の定義
├── go.sum # 依存関係のチェックサム
├── main.go
└── handlers/
└── api.go
# ビルド
go build -cover -o myapp .
特徴:
- ✅
go.modファイルで依存関係を管理 - ✅ どこにでもプロジェクトを配置できる
- ✅ バージョン管理が明確
- ✅ これが標準的な方法
GOPATHモード(GO111MODULE=off)- レガシー
# 古いプロジェクト構造(固定の場所が必要)
$GOPATH/
└── src/
└── github.com/
└── username/
└── myproject/
├── main.go
└── handlers/
└── api.go
# ビルド
GO111MODULE=off go build -cover -o myapp .
特徴:
- ⚠️
$GOPATH/src配下に配置する必要がある - ⚠️
go.modファイルがない - ⚠️ 依存関係の管理が難しい
- ⚠️ 古い方法(新規プロジェクトでは非推奨)
GO111MODULE=offでのカバレッジビルド
基本的な使い方
# GO111MODULE=offモードでカバレッジビルド
GO111MODULE=off go build -cover -o myapp .
重要な違い: モジュールモードとGOPATHモードでは、デフォルトでインストルメンテーションされるパッケージが異なります。
モジュールモードの場合
# GO111MODULE=on(または未設定で1.16以降)
go build -cover -o myapp .
インストルメンテーションされるパッケージ:
- ✅ メインモジュール内のすべてのパッケージ(
go.modで定義されたモジュール)
測定対象:
✅ mydomain.com/myapp
✅ mydomain.com/myapp/handlers
✅ mydomain.com/myapp/models
✅ mydomain.com/myapp/utils
GOPATHモードの場合
# GO111MODULE=off
GO111MODULE=off go build -cover -o myapp .
インストルメンテーションされるパッケージ:
- ✅ コマンドラインで直接指定したパッケージのみ
測定対象:
✅ 現在のディレクトリのパッケージのみ
測定対象外:
❌ サブパッケージ(handlers, models, utilsなど)
-coverpkgで追加パッケージを指定
GOPATHモードでは、サブパッケージも測定するために-coverpkgが必要です。
例1: サブパッケージを含める
# プロジェクト構造
$GOPATH/src/github.com/user/myapp/
├── main.go (mainパッケージ)
├── handlers/
│ └── api.go (handlers パッケージ)
└── models/
└── user.go (models パッケージ)
# ❌ デフォルト(mainパッケージのみ)
GO111MODULE=off go build -cover -o myapp .
# ✅ サブパッケージも含める
GO111MODULE=off go build -cover \
-coverpkg=github.com/user/myapp,github.com/user/myapp/handlers,github.com/user/myapp/models \
-o myapp .
# または、ワイルドカード使用
GO111MODULE=off go build -cover \
-coverpkg=github.com/user/myapp/... \
-o myapp .
実践例1: GOPATHモードでのカバレッジ測定
#!/bin/bash
# gopath-coverage.sh
# GOPATHの確認
echo "GOPATH: $GOPATH"
# プロジェクトのパッケージパス
PKG="github.com/user/myapp"
# すべてのサブパッケージを含める
echo "ビルド中..."
GO111MODULE=off go build -cover \
-coverpkg=$PKG/... \
-o myapp \
$GOPATH/src/$PKG
# 実行
echo "テスト実行中..."
mkdir -p coverage
GOCOVERDIR=coverage ./myapp
# レポート
echo ""
echo "=== カバレッジレポート ==="
go tool covdata percent -i=coverage
モジュールモードとの比較
シナリオ: 同じプロジェクト構造
プロジェクト:
├── main.go
├── handlers/
│ └── api.go
└── models/
└── user.go
モジュールモード(推奨)
# go.modがあるプロジェクト
cat go.mod
# module github.com/user/myapp
# go 1.20
# シンプルなビルド
go build -cover -o myapp .
# すべてのサブパッケージが自動的に含まれる
GOCOVERDIR=coverage ./myapp
go tool covdata percent -i=coverage
# 出力:
# github.com/user/myapp coverage: 100.0%
# github.com/user/myapp/handlers coverage: 85.0%
# github.com/user/myapp/models coverage: 90.0%
GOPATHモード(レガシー)
# $GOPATH/src/github.com/user/myapp にプロジェクトを配置
# サブパッケージを明示的に指定する必要がある
GO111MODULE=off go build -cover \
-coverpkg=github.com/user/myapp/... \
-o myapp .
GOCOVERDIR=coverage ./myapp
go tool covdata percent -i=coverage
# 同じ出力が得られる
違い:
- モジュールモード:
-coverpkg不要(自動) - GOPATHモード:
-coverpkg必要(手動)
実践例2: レガシープロジェクトのマイグレーション
古いGOPATHプロジェクトを段階的にモジュールモードに移行する例:
#!/bin/bash
# migration-coverage.sh
PKG_PATH="github.com/company/oldproject"
GOPATH_SRC="$GOPATH/src/$PKG_PATH"
echo "=== 古いGOPATHモードでのカバレッジ ==="
# GOPATHモードでビルド
cd $GOPATH_SRC
GO111MODULE=off go build -cover \
-coverpkg=$PKG_PATH/... \
-o oldapp .
# 実行
mkdir -p coverage_gopath
GOCOVERDIR=coverage_gopath ./oldapp
# レポート
echo "GOPATHモード結果:"
go tool covdata percent -i=coverage_gopath
echo ""
echo "=== モジュールモードへ移行 ==="
# go.modを作成
go mod init $PKG_PATH
go mod tidy
# モジュールモードでビルド
go build -cover -o newapp .
# 実行
mkdir -p coverage_module
GOCOVERDIR=coverage_module ./newapp
# レポート
echo "モジュールモード結果:"
go tool covdata percent -i=coverage_module
echo ""
echo "移行完了!go.modを確認してください。"
なぜモジュールモードを使うべきか
モジュールモードの利点
- どこにでも配置可能
# モジュールモード: どこでもOK
~/projects/myapp/
/tmp/test/myapp/
/var/www/myapp/
# GOPATHモード: $GOPATH/src配下のみ
$GOPATH/src/github.com/user/myapp/
- 依存関係の管理が簡単
# go.modで明確
module myapp
require (
github.com/gin-gonic/gin v1.9.0
github.com/lib/pq v1.10.9
)
- バージョン管理
# 特定のバージョンを指定可能
go get github.com/gin-gonic/gin@v1.9.0
- 再現性のあるビルド
# go.sumでハッシュを記録
# チーム全員が同じバージョンを使用
トラブルシューティング
問題1: GOPATHモードでサブパッケージが測定されない
$ GO111MODULE=off go build -cover -o myapp .
$ GOCOVERDIR=coverage ./myapp
$ go tool covdata percent -i=coverage
main coverage: 100.0% of statements
# サブパッケージが表示されない
解決策:
# -coverpkgでサブパッケージを明示的に指定
GO111MODULE=off go build -cover \
-coverpkg=github.com/user/myapp/... \
-o myapp .
問題2: GOPATHが設定されていない
$ GO111MODULE=off go build -cover -o myapp .
error: cannot find package "..." in any of:
/usr/local/go/src/... (from $GOROOT)
($GOPATH not set)
解決策:
# GOPATHを設定
export GOPATH=$HOME/go
# またはモジュールモードを使用(推奨)
unset GO111MODULE # デフォルトのモジュールモードを使用
go build -cover -o myapp .
問題3: 混在した環境
# プロジェクトにgo.modがあるのにGO111MODULE=offを使用
$ ls
go.mod go.sum main.go
$ GO111MODULE=off go build -cover -o myapp .
# 予期しない動作
解決策:
# go.modがある場合はモジュールモードを使う
go build -cover -o myapp .
# またはgo.modを削除してGOPATHモードに完全移行
# (非推奨)
推奨事項
新規プロジェクト
# ✅ モジュールモードを使用
go mod init github.com/user/myapp
go build -cover -o myapp .
既存のGOPATHプロジェクト
オプション1: モジュールモードへ移行(推奨)
cd $GOPATH/src/github.com/user/myapp
go mod init github.com/user/myapp
go mod tidy
go build -cover -o myapp .
オプション2: GOPATHモードを継続(レガシー)
# -coverpkgを必ず使用
GO111MODULE=off go build -cover \
-coverpkg=github.com/user/myapp/... \
-o myapp .
まとめ
| モード | GO111MODULE | デフォルト測定範囲 | -coverpkgの必要性 |
|---|---|---|---|
| モジュール | on(推奨) | モジュール全体 | 通常不要 |
| GOPATH | off(レガシー) | 指定パッケージのみ | サブパッケージ測定に必須 |
重要なポイント:
- ✅
GO111MODULE=offでもgo build -coverは動作する - ⚠️ GOPATHモードではデフォルトで指定パッケージのみ測定
- ✅
-coverpkgでサブパッケージも含められる - 🎯 新規プロジェクトはモジュールモードを使用すること
- 📚 レガシープロジェクトも段階的にモジュールモードへ移行推奨
ベストプラクティス:
# 新規プロジェクト・推奨方法
go mod init myapp
go build -cover -o myapp .
# レガシーサポートが必要な場合のみ
GO111MODULE=off go build -cover -coverpkg=./... -o myapp .
おわりに
本日は、Go言語の統合テストのカバレッジについて解説しました。

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

コメント