golangの単体テストは、golangの標準パッケージ
testing
を使用することで作成することができる。
testing
検証環境のディレクトリ構造
golang
├main.go
└person
├person.go
└person_test.go
VSCode上での単体テスト作成方法
テストしたいメソッドの上でコンテキストメニューを開き、
Go:generate Unit Tests For Function
を選択するとテストコードが生成される。
testing
は{テスト対象のソース名}_test.go
というファイルを生成する。
package main
import (
"fmt"
"./person"
)
func main() {
fmt.Println("start")
person.InitPerson()
}
package person
import "fmt"
// Person Recording Persons Score & rank.
type Person struct {
name string
english int
rank string
}
// InitPerson doing Initialize Person.
func InitPerson() {
Bob := Person{"Bob", 60, ""}
Bob.rank = Score(Bob)
fmt.Printf("Name:%v\n", Bob.name)
fmt.Printf("Score:%v\n", Bob.english)
fmt.Printf("rank:%v\n", Bob.rank)
}
// Score Return rank by score.
func Score(p Person) string {
if p.english > 80 {
return "A"
} else if p.english > 60 {
return "B"
} else {
return "C"
}
}
person.goのScoreメソッドに対して、下記のテストコードが生成される。
package person
import (
"testing"
)
func TestScore(t *testing.T) {
type args struct {
p Person
}
tests := []struct {
name string
args args
want string
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Score(tt.args.p); got != tt.want {
t.Errorf("Score() = %v, want %v", got, tt.want)
}
})
}
}
生成されたコードのstructにテスト対象の値を渡し、テストを実行することもできるが、
今回はスケルトンを使用せず、下記の通りテストコードを作成した。
package person
import (
"testing"
)
func TestScore_1(t *testing.T) {
p := Person{"Bob", 60, ""}
actual := Score(p)
expected := "C"
if actual != expected {
t.Errorf("got %v want %v", actual, expected)
}
}
VSCode上で、メソッド上部に表示されるrun test
を実行すると
メソッド単位でテストを実行することができる。
実行すると、下記の結果がターミナルに出力される。
Running tool: /usr/local/go/bin/go test -timeout 30s -run ^(TestScore_1)$
PASS
ok _/Users/username/golang/golang/person 0.010s
Success: Tests passed.
また、テストコードを格納しているディレクトリで
go test .
を実行すると、ディレクトリ内の全テストを実行する事ができる。
先程のコードに新たに2ケース追加した。
失敗時の動作を確認するためTestScore_3はNGケースを設定している。
package person
import (
"testing"
)
func TestScore_1(t *testing.T) {
p := Person{"Bob", 90, ""}
actual := Score(p)
expected := "A"
if actual != expected {
t.Errorf("got %v want %v", actual, expected)
}
}
func TestScore_2(t *testing.T) {
p := Person{"Bob", 80, ""}
actual := Score(p)
expected := "B"
if actual != expected {
t.Errorf("got %v want %v", actual, expected)
}
}
//NG case
func TestScore_3(t *testing.T) {
p := Person{"Bob", 60, ""}
actual := Score(p)
expected := "B"
if actual != expected {
t.Errorf("got %v want %v", actual, expected)
}
}
上記テストの実行結果は下記の通りである。
失敗すると、正常な結果が得られなかったソースの箇所と、
設定したエラーメッセージがターミナルに表示される。
1箇所エラーが発生した時点で、後続のコードは実行されない。
$ go test .
--- FAIL: TestScore_3 (0.00s)
person_test.go:31: got C want B
FAIL
FAIL _/Users/username/golang/golang/person 0.006s
FAIL
カバレッジの取得
-cover
オプションをつけることで、カバレッジを取得することができる。
go test . -cover
ok _/Users/username/golang/golang/person 0.011s coverage: 50.0% of statements
また、カバレッジをHTMLとして出力することもできる。
test
の-coverprofile
オプションで、カバレッジプロファイルをファイルに出力し、
出力したファイルをgo tool cover
でHTMLファイルへ変換する。
$go test -coverprofile=cover.out ./
ok _/Users/username/golang/golang/person 0.007s coverage: 50.0% of statements
$ go tool cover -html=cover.out -o cover.html
カバレッジをhtmlで表示すると下記の通り。