Go言語でテストのカバレッジを計測する

Go1.2からテストカバレッジの計測がサポートされています。
http://golang.org/doc/go1.2#cover


私が公開しているgo-pop3パッケージを使ってテストカバレッジを計測してみたいと思います。
ソースコードは以下に配置されているものとします。

GOPATH/src/github.com/taknb2nch/go-pop3/

まずはテストが通ることを確認します。

$ go test
PASS
ok      github.com/taknb2nch/go-pop3    0.113s

では次にカバレッジを計測してみます。

$ go test -cover
go tool: no such tool "cover"; to install:
        go get code.google.com/p/go.tools/cmd/cover

さすがWindowsです、coverツール(コマンド)が標準ではインストールされていないようです。
(ちなみにUbuntu上に用意した環境には最初から入っていました)
go get コマンドでcoverをインストールして、再度実行します。

$ go get code.google.com/p/go.tools/cmd/cover
$ go test -cover
PASS
coverage: 68.4% of statements
ok      github.com/taknb2nch/go-pop3    0.123s

68.4%カバーできているということのようです。


今後は-coverprofileオプションを指定してテストを実行します。
このオプションは-coverで実行し、結果を指定したファイルに出力してくれるようです。ただ出力されたファイルの中身はよくわかりません。

$ go test -coverprofile=coverage.out
PASS
coverage: 68.4% of statements
ok      github.com/taknb2nch/go-pop3    0.116s

出力結果は同じですが、同じディレクトリにcoverage.outファイルが作成されています。
次にgo tool coverコマンドで-funcオプションに先程出力されたcoverage.outを指定し実行します。

$ go tool cover -func=coverage.out
github.com\taknb2nch\go-pop3\pop3.go:           Dial                    0.0%
github.com\taknb2nch\go-pop3\pop3.go:           NewClient               80.0%
github.com\taknb2nch\go-pop3\pop3.go:           User                    100.0%
github.com\taknb2nch\go-pop3\pop3.go:           Pass                    100.0%
github.com\taknb2nch\go-pop3\pop3.go:           Stat                    100.0%
github.com\taknb2nch\go-pop3\pop3.go:           Retr                    75.0%
github.com\taknb2nch\go-pop3\pop3.go:           List                    100.0%
github.com\taknb2nch\go-pop3\pop3.go:           ListAll                 80.0%
github.com\taknb2nch\go-pop3\pop3.go:           Uidl                    78.6%
github.com\taknb2nch\go-pop3\pop3.go:           UidlAll                 80.0%
github.com\taknb2nch\go-pop3\pop3.go:           Dele                    100.0%
github.com\taknb2nch\go-pop3\pop3.go:           Noop                    100.0%
github.com\taknb2nch\go-pop3\pop3.go:           Rset                    100.0%
github.com\taknb2nch\go-pop3\pop3.go:           Quit                    100.0%
github.com\taknb2nch\go-pop3\pop3.go:           ReceiveMail             0.0%
github.com\taknb2nch\go-pop3\pop3.go:           cmdSimple               75.0%
github.com\taknb2nch\go-pop3\pop3.go:           cmdStatOrList           76.5%
github.com\taknb2nch\go-pop3\pop3.go:           cmdReadLines            75.0%
github.com\taknb2nch\go-pop3\pop3.go:           Close                   100.0%
github.com\taknb2nch\go-pop3\pop3.go:           convertNumberAndSize    72.7%
github.com\taknb2nch\go-pop3\pop3.go:           convertNumberAndUid     75.0%
github.com\taknb2nch\go-pop3\pop3proto.go:      Error                   100.0%
github.com\taknb2nch\go-pop3\pop3proto.go:      NewConn                 100.0%
github.com\taknb2nch\go-pop3\pop3proto.go:      Close                   100.0%
github.com\taknb2nch\go-pop3\pop3proto.go:      NewReader               100.0%
github.com\taknb2nch\go-pop3\pop3proto.go:      ReadLine                100.0%
github.com\taknb2nch\go-pop3\pop3proto.go:      ReadLines               100.0%
github.com\taknb2nch\go-pop3\pop3proto.go:      ReadToPeriod            100.0%
github.com\taknb2nch\go-pop3\pop3proto.go:      ReadResponse            75.0%
github.com\taknb2nch\go-pop3\pop3proto.go:      parseResponse           100.0%
github.com\taknb2nch\go-pop3\pop3proto.go:      NewWriter               100.0%
github.com\taknb2nch\go-pop3\pop3proto.go:      WriteLine               66.7%
total:                                          (statements)            68.4%

するとテスト対象の関数、メソッドごとにガバレッジが表示されます。Dial、ReceiveMail、WriteLineが低いので全体も低くなっているようです。
この結果を視覚化することもできます。先程と同じように今度は-htmlオプションに先程出力されたcoverage.outを指定し実行します。

$ go tool cover -html=coverage.out

すると、ブラウザが起動し以下のような画面が表示されます。

緑色の部分はテストが書けている部分、赤の部分はそうでない部分になります。この画面を見ればどのようなパターンのテストが書けていないかわかります。


また、ステートメントが実行されたかどうかだけでなく、何回実行されたかも計測できます。
回数も計測する場合にはgo testコマンドに-covermove=countを追加して実行します。

$ go test -coverprofile=count.out -covermode=count
PASS
coverage: 68.4% of statements
ok      github.com/taknb2nch/go-pop3    0.116s

出力結果は以下のように表示されます。

$ go tool cover -html=count.out


マウスを左端に持って行くと回数がポップアップで表示されます。
ただこれの何が嬉しいのかはまだピンときません。

まとめ

Go言語ではテストカバレッジの計測がサポートされていて、簡単に計測、視覚化することができ、テストの精度を上げることができそうです。
ただ、あくまで実装した関数、メソッドの内容に対して、どれだけテストがカバーできているかを表しているだけなので、そもそも関数やメソッドが仕様を満たしているかを発見することはできません。そのためには仕様を網羅できるテストを書かなくてはならないと思います。そうするためにはTDDがどうこうという話になってくるので、ここでは触れません。