Ginkgoには、DescribeTableというTable Driven Testの仕組みが用意されています。
DescribeTableを使わないでfor文でテストデータの数だけIt()を呼ぶ方法もありますが、テストデータをハードコーディングする場合はDescribeTableを使うと便利です。
以下、DescribeTableの使い方の例を示します。
BeforeEach/BeforeSuiteの実行前にテストデータが作れる場合
公式のサンプルコードそのまま。
import (
. "github.com/onsi/ginkgo/extensions/table"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Math", func() {
DescribeTable("the > inequality",
func(x int, y int, expected bool) {
Expect(x > y).To(Equal(expected))
},
Entry("x > y", 1, 0, true),
Entry("x == y", 0, 0, false),
Entry("x < y", 0, 1, false),
)
})
BeforeEach/BeforeSuiteの実行後でないとテストデータが作れない場合
bookという変数があり、テストデータを作るのにbookを作る必要があるが、bookはBeforeEachでないと作れない状況を考えます。
var _ = Describe("Book", func() {
// ここでは、テストデータを作るのに必要。BeforeEachでないと作れないとする。
var book Book
BeforeEach(func() {
book = CreateBook()
})
type TestData struct {
id int
expected bool
}
DescribeTable("Find",
func(lazyTestData func() TestData) {
// テストデータを生成する:
testParam := lazyTestData()
Expect(DoesExist(testParam.id)).To(Equal(testParam.expected))
},
// テストデータそのものではなく、テストデータを作る関数を渡す。
// このコード実行時点では、テストデータを生成するのに必要なbookが作られていないため
Entry("本が見つかること", func() TestData {
return TestData{
id: book.ID,
expected: true,
}
}),
Entry("本が見つからないこと", func() TestData {
return TestData{
id: -1,
expected: false,
}
}))
})
最初に示した例のように、Entry()の引数に直接テストデータを渡すことはできません。DescribeTable()の実行時点では、BeforeEachが呼ばれていないので、テストデータを作れていないからです。
そこで、テストデータそのものではなく、テストデータを作成する関数をDescribeTableには渡します。最終的には、テスト実行時(DescribeTableの第2引数の関数の実行時)に、テストデータを作成する関数を呼び出すことでテストデータを作ります。このタイミングであれば、BeforeEachが呼ばれているので、テストデータは作れます。
示してみたもののこのパターンとのときは、素直にIt()を1つずつ書く、各Itの中でテストデータを作る、検証処理は関数化して各Itで呼ぶ、とした方が分かりやすいかと思います。