goを始めようと思い、unittestの書き方をまずは理解しようと思ったときの備忘録。
ディレクトリ配置
~/dev/work/go/src
% tree
.
├── funcs.go
├── funcs_test.go
└── main.go
ファイルの内容
main.go
package main
import (
"fmt"
)
func main() {
a := int32(1)
b := int32(2)
fmt.Println(Sum(a, b))
}
funcs.go
package main
func Sum(a int32, b int32) int32 {
return a + b
}
- 単に
1 + 2 = 3
という計算を、関数Sum
でやっているだけ -
Sum
は、引数a
,引数b
を足して、結果をリターンするだけ
GOPATHを ~/dev/work/go
に通っている状態にして、試しに実行するとこうなる。
% cd ~/dev/work/go/src
% go run main.go funcs.go
3
まぁ、 3
と出る。
ちなみに、 go run
には引数で指定したファイルしか渡らないので、 go run main.go
だけだと func Sum
が存在しない旨のエラーが出る。(というのもgoのノウハウとして学んだ)
で、次にunittest。
同ディレクトリに funcs_test.go
があるのでその内容。
funcs_test.go
package main
import (
"testing"
)
type Provider struct {
a int32
b int32
exp int32
}
func TestSum(t *testing.T) {
providers := []Provider{
Provider{1, 2, 3},
Provider{2, 4, 6},
Provider{3, 5, 8}}
for i := range providers {
testSum(t, providers[i])
}
}
func testSum(t *testing.T, p Provider) {
actual := Sum(p.a, p.b)
exp := p.exp
if actual != exp {
t.Errorf("actual %v\nwant %v", actual, exp)
}
}
CakePHPのProvider的にやりたかったので、こんな感じにしてみた。
ポイントと、goに慣れてない自分的に苦労したのは以下の点。
-
goだと、
TestXXX
という関数がテストとみなされるようなので、内部で呼ぶものはtestXXX
とした -
テストデータを一括で複数渡したかったが、そのやり方に苦労した。具体的には、
- ProviderというStructを宣言
- そのSliceを作り、初期値にa, b, exp(期待値)をセット
-
TestSum
のループ内で、testSum
を呼び、その際Providerの内容を1つずつ渡す - actual(実際の計算結果)と、exp(期待値)に差がある場合、
t.Errorf
を呼ぶ。これが assertEqualsに相当
もっといいやり方があるような気がする。。。。
実際に実行してみる。
% cd ~/dev/work/go/src
% go test funcs.go funcs_test.go
ok command-line-arguments 0.005s
ためしに、 Provider{3, 5, 8}
の部分を Provider{3, 5, 9}
とかに変えてみるとこうなる。
(3 + 5 = 9というデータにしてみたことになる)
% go test funcs.go funcs_test.go
--- FAIL: TestSum (0.00s)
funcs_test.go:33: actual 8
want 9
FAIL
FAIL command-line-arguments 0.007s
ちゃんとアサーションがコケた。(まぁ当然・・・)
とりあえずここまではわかったので、次はモックの方法を学んでまた書いておく。