はじめに
最近Goの勉強をしてて、簡単なWebサーバーを作ってみたり、コマンドラインで動作するツールを作ったり、、、としているんですけど、そういやテスト書いたことないなあと思って今回の記事を書くことにしました!
Ginkgoを選んだ理由
Ginkgoの書き方がなんとなくrspecに似てるからです。
昔Railsを書いていたことがあるので、簡単に書けるんじゃないかな〜っていう安易な発想です。
テストの準備
Ginkgoをインストールします。
go get github.com/onsi/ginkgo/ginkgo
go get github.com/onsi/gomega/...
ディレクトリとテスト用ファイルを作成します。
mkdir fizzbuzz
cd fizzbuzz
ginkgo bootstrap
ginkgo generate fizzbuzz
実装
今回作成するテストケースは以下の通りとします。よく見るFizzBuzzですね。
- 数値が3の倍数であれば「Fizz」を返す
- 数値が5の倍数であれば「Buzz」を返す
- 数値が3の倍数かつ5の倍数であれば「FizzBuzz」を返す
- 数値が3の倍数でも5の倍数でもなければ、そのまま文字列に変換して返す
早速ですが実装は以下の通りです。
シンプルなFizzBuzzなので特に何もないですね。
fizzbuzz.go
package fizzbuzz
import (
"strconv"
)
func Convert(i int) (string, error) {
if i%15 == 0 {
return "FizzBuzz", nil
}
if i%3 == 0 {
return "Fizz", nil
}
if i%5 == 0 {
return "Buzz", nil
}
return strconv.Itoa(i), nil
}
こちらがテストコードになります。
こういう書き方がいいのかダメなのかもわかってないですけど、それっぽく書いてみました。
fizzbuzz_test.go
package fizzbuzz
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"strconv"
)
var _ = Describe("fizzbuzz", func() {
Describe("Convertメソッド", func() {
Context("引数が3の倍数でも5の倍数でもない場合", func() {
data := []int{1, 4, 8, 11, 13, 14, 17, 19, 23, 26}
for idx := range data {
// rangeの第2引数はポインタなのでそのままアサーションに使用すると正しくテストが実行されない
v := data[idx]
r, err := Convert(v)
It("そのまま文字列変換した値を返すこと", func() {
Expect(r).To(Equal(strconv.Itoa(v)))
})
It("エラーがnilであること", func() {
Expect(err).To(BeNil())
})
}
})
Context("引数が3の倍数", func() {
data := []int{3, 6, 9, 12, 18, 21, 24, 27, 33, 36}
for idx := range data {
// rangeの第2引数はポインタなのでそのままアサーションに使用すると正しくテストが実行されない
v := data[idx]
r, err := Convert(v)
It("Fizzという文字列を返すこと", func() {
Expect(r).To(Equal("Fizz"))
})
It("エラーがnilであること", func() {
Expect(err).To(BeNil())
})
}
})
Context("引数が5の倍数", func() {
data := []int{5, 10, 20, 25, 35, 40, 50, 55, 65, 70}
for idx := range data {
// rangeの第2引数はポインタなのでそのままアサーションに使用すると正しくテストが実行されない
v := data[idx]
r, err := Convert(v)
It("Buzzという文字列を返すこと", func() {
Expect(r).To(Equal("Buzz"))
})
It("エラーがnilであること", func() {
Expect(err).To(BeNil())
})
}
})
Context("引数が3の倍数かつ5の倍数", func() {
data := []int{15, 30, 45, 60, 75, 90, 105, 120, 135, 150}
for idx := range data {
// rangeの第2引数はポインタなのでそのままアサーションに使用すると正しくテストが実行されない
v := data[idx]
r, err := Convert(v)
It("FizzBuzzという文字列を返すこと", func() {
Expect(r).To(Equal("FizzBuzz"))
})
It("エラーがnilであること", func() {
Expect(err).To(BeNil())
})
}
})
})
})
おわりに
今回は、Goで簡単なテストを書いてみました。
標準のテストを書いたことがない状態で、いきなりGinkgoを書いていいものか悩みましたが、まあよしとしましょう。
何かの参考になれば幸いです。