Goでテストしてカバレッジ計測
はじめに
平下CTO@sweeepです。Go言語でのテスト方法やカバレッジ計測などをこちらをサンプルに解説します。→ GoでファイルのValidation方法など
本記事の内容です。
- Goのテスト
- テストのsetup/teardown
- カバレッジ計測
- テスト実行結果
Goのテスト
まずxxx_test.goというファイルを作成し、testingとassertをimportします(packageはテスト対象と同じ)。
テストモジュールにはTestifyを使用しています。
Goテストモジュール Testifyをつかってみた | DevelopersIO https://dev.classmethod.jp/articles/go-testify/
以下のようなパッケージが含まれており、テストコードが簡潔にかけます。
assert package
require package
mock package
suite package
package file
import (
"testing"
"github.com/stretchr/testify/assert"
)
関数名にはTestXXXと先頭に[Test]をつけます。
func TestCheckFileSize(t *testing.T) {
...
}
以下はテスト対象のファイルサイズチェック処理です。
func CheckFileSize(size int64) (int64, error) {
if size > MaxSize { // MaxSizeより大きい場合はエラー
return size, fmt.Errorf("size: %v error: %w", size, ErrFileSize)
}
return size, nil
}
テスト処理は下記記事を参考にAAA(Arrange/Action/Assert)を意識してテスト準備、テストの実行、テストの検証と書くようにしています。
それは、テストコードを読みやすくするための指針です。AAA は arrange, act, assert の略語で、arrange は『準備』、act は『実行』、assertは『検証』を表します。
準備はテスト用のデータの作成、実行はテストしたい関数やメソッドを実行すること、検証は実行の結果得られた値や変化が期待したものであるかどうかを確認することになります。
func TestCheckFileSize(t *testing.T) {
// arrange
f, _ := os.Open("../../sample/image.jpg")
defer func() {
_ = f.Close()
}()
// action
fi, _ := f.Stat()
_, actual := CheckFileSize(fi.Size())
// assert
assert.ErrorIs(t, nil, actual)
}
...
テストのsetup/teardown
テスト前にsetupでコンフィグやenv設定したり、テスト終了後にteardownでテスト用のデータのクリア処理したいことがあると思います。以下のようにsetupとteardown定義し、TestMainで呼び出します。
// テストの開始・終了
func TestMain(m *testing.M) {
setup()
ret := m.Run()
if ret == 0 {
teardown()
}
os.Exit(ret)
}
// テスト初期設定
func setup() {
log.Println("test start!")
}
// テスト終了処理
func teardown() {
log.Println("test end!")
}
実行すると以下の様にテストケースの開始と終了にsetupとteardownが呼ばれます。
file $ go test -v -coverpkg=. ./...
2022/02/26 15:59:26 test start!
...
2022/02/26 15:59:26 test end!
テストの実行とカバレッジ計測
テストの実行は以下のコマンドで実行します。[-coverpkg]オプションでカバレッジを計測します。
$ go test -v -coverpkg=. ./...
カバレッジ計測結果は以下のように表示されます(80%ですね)。
coverage: 80.0% of statements in .
ok github.com/hirac1220/go-file-validate/utils/file 0.119s coverage: 80.0% of statements in .
どの処理がカバーされていないか確認したい場合は[-coverprofile]でプロファイル作成し、htmlへ変換し出力します。
$ go test -v -coverprofile=cover_file.out -coverpkg=./...
$ go tool cover -html=cover_file.out -o cover_file.html
すると添付のようにカバーされている処理は緑で、カバーされていない処理が赤く表示されます(サンプルではエラー処理がカバーできていないですね)。
テスト実行結果
コマンド打つのがちょっとまんどいので、Makefileでテスト実施しています。
test_file:
go test -v -coverpkg=. ./...
test_cover_file:
go test -v -coverprofile=cover_file.out -coverpkg=./...
go tool cover -html=cover_file.out -o cover_file.html
テスト実行結果は以下のようになり、すべてPASSしてカバレッジが80%というのがわかります(失敗するとFAILが表示されます)
file $ make test_file
go test -v -coverpkg=. ./...
2022/02/26 15:59:26 test start!
=== RUN TestCheckFileSize
--- PASS: TestCheckFileSize (0.00s)
=== RUN TestValidateJPEG
--- PASS: TestValidateJPEG (0.00s)
=== RUN TestValidateJPG
--- PASS: TestValidateJPG (0.00s)
=== RUN TestValidatePNG
--- PASS: TestValidatePNG (0.00s)
=== RUN TestJPGExtToContentType
--- PASS: TestJPGExtToContentType (0.00s)
=== RUN TestJPEGExtToContentType
--- PASS: TestJPEGExtToContentType (0.00s)
=== RUN TestPNGExtToContentType
--- PASS: TestPNGExtToContentType (0.00s)
PASS
coverage: 80.0% of statements in .
2022/02/26 15:59:26 test end!
ok github.com/hirac1220/go-file-validate/utils/file 0.119s coverage: 80.0% of statements in .
まとめ
今回はGo言語でのテストとカバレッジ計測ついて解説しました。
テストがあるおかげで、大幅な仕様変更時やリファクタリング時にも思い切った変更ができるようになったと感じています。
カバレッジ数値目標ですが75%ぐらいがよいのかな、と思っています。ただ、カバレッジを目標に無理くりテストコードを書くのは本末転倒な気がします。適切なテストコードとマニュアルテストの組合せで品質を作り込むことが大事かな、と思っています。
使用したサンプルはこちらのGitHubレポジトリにあります。
Discussion