Goテストの基本
- testingパッケージを使う。
- ファイル名は必ず_test.goがつくようにする。
- testingパッケージをimportする
- 関数名はfunc TestXxx (t *testing.T)の形式にする
テスト実行
以下のコードをサンプルとして動かしてみる。
package gotest
import (
"testing"
)
func Test_Division_1(t *testing.T) {
if i, e := Division(6, 2); i != 3 || e != nil { //try a unit test on function
t.Error("除算関数のテストが通りません") // もし予定されたものでなければエラーを発生させます。
} else {
t.Log("はじめのテストがパスしました") //記録したい情報を記録します
}
}
func Test_Division_2(t *testing.T) {
t.Error("パスしません")
}
テストを全て実行
go test
ただ、これではテスト結果がわかりにくい。go testを実行するとテストがパスする情報は表示されない。
表示させるには-vをつける必要がある。
go test -v
1つのテストメソッドを実行
go test -run メソッド名
Hello Worldのテストを書いてみる
go_test
├── hello.go
└── hello_test.go
go_testというディレクトリにhelloworldを出力するhello.goとテストするためのhello_test.goを置く。
package main
import "fmt"
func getHello() string {
return "Hello World"
}
func main() {
fmt.Println(getHello())
}
hello.goは実行すればHelloWordの出力。これをテストします。
package main
import (
"testing"
)
func TestHello(t *testing.T) {
if "Hello World" != getHello() {
t.Fatal("failed test")
}
}
testingをimport。ファイル名は必ず〇〇_test.goにしなければいけないようなので、hello_test.go。メソッド名も規則に則りTestHello()です。
これを実行すると、テストは通りますね。
go test -v
assertやexpect的なものがない?
go言語にはphpのassertやrubyのexpectのようなものがないみたいです。
公式のgithubのサンプルを少しみてみましょう。
func runExamples(matchString func(pat, str string) (bool, error), examples []InternalExample) (ran, ok bool) {
ok = true
var eg InternalExample
for _, eg = range examples {
matched, err := matchString(*match, eg.Name)
if err != nil {
fmt.Fprintf(os.Stderr, "testing: invalid regexp for -test.run: %s\n", err)
os.Exit(1)
}
if !matched {
continue
}
ran = true
if !runExample(eg) {
ok = false
}
}
return ran, ok
}
https://github.com/golang/go/blob/master/src/testing/example.go
if文で行っていますね。
ちょっと不思議な感じですが、これがgoなのでしょう。
ドキュメントに理由が書いてあります。
アサーション機能はないのですか?
アサーション機能は無いのですか?¶
Goはアサーション機能を提供しません。アサーションが便利なのは否定できませんが、我々の経験上プログラマは、それを適切なエラー処理とエラー出力を避けるために使っています。適切なエラー処理とは、サーバがクラッシュする代わりに致命的ではないエラーを発生するにとどめ、処理を続けられるということを意味しています。適切なエラー出力は、エラーが直接的や部分的だったとき、クラッシュ時の膨大なトレースを翻訳する作業からプログラマを開放することを意味します。正確なエラー出力は、エラーを見つけたプログラマーがそのコードに精通していない時ほど重要です。
いや、それでもAssert使いたい
Goの考えはわかった。でも、私はassertを使いたい。そんな時にはassertのパッケージがあるので、それを使いましょう。
https://github.com/stretchr/testify
これです。
こんな使い方ができるようです。
func TestSomething(t *testing.T) {
// assert equality
assert.Equal(t, 123, 123, "they should be equal")
// assert inequality
assert.NotEqual(t, 123, 456, "they should not be equal")
// assert for nil (good for errors)
assert.Nil(t, object)
// assert for not nil (good when you expect something)
if assert.NotNil(t, object) {
// now we know that object isn't nil, we are safe to make
// further assertions without causing any errors
assert.Equal(t, "Something", object.Value)
}
https://github.com/stretchr/testify
テストっぽい感じがしますね。
さっきのHello Wordのテストをこっちに書き換えます。
go get github.com/stretchr/testify/assert
//インストール
package main
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestHello(t *testing.T) {
assert.Equal(t, getHello(), "Hello World")
}