ローカル環境でコードカバレッジを確認する
まずテストを記述する必要がある. How to Write Go Code を参考にして,
func Greet(name string, lang string) string {
switch lang {
case "en":
return fmt.Sprintf("Hello, %s.", name)
case "ja":
return fmt.Sprintf("こんにちは, %s.", name)
}
return "..."
}
という関数に対して,
type TestCase struct {
Name string
Language string
}
func TestGreet(t *testing.T) {
cases := []struct {
in TestCase
expected string
}{
{TestCase{Name: "World", Language: "en"}, "Hello, World."},
{TestCase{Name: "Kazumasa", Language: "ja"}, "こんにちは, Kazumasa."},
}
for _, c := range cases {
actual := Greet(c.in.Name, c.in.Language)
if actual != c.expected {
t.Errorf("Greet(%q, %q) == %q, expect %q",
c.in.Name, c.in.Language, actual, c.expected)
}
}
}
というようなテストを書いてみる. (完全なソースファイルは ここ にある.)
テストを用意したところで, go test
を -cover
オプション付きで実行すると, カバレッジが出力される.
$ go test -cover ./feature/
ok github.com/kkohtaka/go-scaffold/feature 0.006s coverage: 75.0% of statements
普通はどの行がカバーされていないかが知りたいと思うので HTML で出力してみる. そこで, go test
の -coverprofile
オプションでカバレッジプロファイルをファイルへ出力し, go tool cover
で HTML へ変換する.
$ go test -coverprofile=cover.out ./feature/
ok github.com/kkohtaka/go-scaffold/feature 0.006s coverage: 75.0% of statements
$ go tool cover -html=cover.out -o cover.html
$ open cover.html
出力された HTML のサンプルは このような感じ.
CI と組み合わせてコードカバレッジを共有する
ローカル環境でコードカバレッジを確認するだけでなく, 他の開発者とコードカバレッジを共有する方法として, Codecov と Coveralls を試してみた. また, CI サービスとしては Travis CI を利用した. (同じ要領で Drone.io でも動作を確認した.)
流れとしては,
- CI 環境で必要なパッケージをインストール
- テストを実行してカバレッジプロファイルを出力
- Codecov, Coveralls それぞれの用意しているスクリプトで結果をアップロード
となる. .travis.yml は下記のような感じ.
before_install:
# Codecov に必要なファイルをインストール
- go get github.com/onsi/gomega
- go get github.com/onsi/ginkgo
# Coveralls に必要なファイルをインストール
- go get github.com/mattn/goveralls
# 両方に必要なファイルをインストール
- go get golang.org/x/tools/cmd/cover
script:
# テストを実行してカバレッジプロファイルを出力
- ./go_test.sh
after_success:
# Codecov へ結果をアップロード
- bash <(curl -s https://codecov.io/bash)
# Coveralls へ結果をアップロード
- $GOPATH/bin/goveralls -coverprofile=coverage.txt -covermode=count -service=travis-ci -repotoken $COVERALLS_TOKEN
注意しなければいけない点として, go test -cover
が複数の Go パッケージのテストをサポートしていないので, カバレッジの取得対象が複数のパッケージを含んでいる場合には各々のカバレッジ結果をマージする必要がある. ここでは下記のようなスクリプトを記述することで対応した. (完全なソースファイルは ここ にある.)
echo "mode: $COVERMODE" > $COVERAGE_FILE
for PKG in $(go list ./...); do
go test -v -coverprofile=$TMP_FILE -covermode=$COVERMODE $PKG
if [ -f $TMP_FILE ]; then
# カバレッジ結果の先頭の "mode: ..." という行を削除
cat $TMP_FILE | tail -n +2 >> $COVERAGE_FILE
rm $TMP_FILE
fi
done
Codecov, Coveralls それぞれでの出力結果は下記で確認できる.
- Codecov: https://codecov.io/gh/kkohtaka/go-scaffold
- Coveralls: https://coveralls.io/github/kkohtaka/go-scaffold