🙌

golangでテストを書くならテーブルドリブンテスト

2017/12/03に公開

はじめに

golangでアプリケーション開発が流行ってきている中でテストを書く機会も多いと思います。
その中で複数のデータセットでテストを行うと思いますが、その場合分けを変数に格納し毎回if文を書いて判別しているコードを見かけたのでこの記事を書こうと思いました。

公式wikiにも載っていますが

Writing good tests is not trivial, but in many situations a lot of ground can be covered with table-driven tests.

良いテストを書くのは簡単ではないが、多くの状況はテーブル駆動型でカバーできる。

らしいです。
最初は何も見ずにテストを書いていて分かりづらいなと感じていたらこの書き方の方が良いよと指摘をいただいたので、そんな方にはこの記事を見て欲しいなと思います。

Sample

年齢から料金を出すような関数を実装。

sample.go
package sample

func FeeFromAge(age int) int {
	if age <= 12 {
		return 1000
	} else {
		return 2000
	}
}

この関数に対してテストコードを実装します。
まずは単純なテスト

sample_test.go
package sample

import "testing"

func TestFeeFromAge(t *testing.T) {
	errFmt := "The judgment of fee is wrong\n"

	age := 10
	fee := 1000
	if FeeFromAge(age) != fee {
		t.Error(errFmt)
	}

	age = 20
	fee = 2000
	if FeeFromAge(age) != fee {
		t.Error(errFmt)
	}
}

ものすごく単純に行うとこのようなテストになるかと思います。

次にテーブルドリブンテスト。

sample_test.go
package sample

import "testing"

func TestFeeFromAge(t *testing.T) {
	cases := []struct {
		age  int
		fee int
	}{
		{age: 10, fee: 1000},
		{age: 20, fee: 2000},
	}

	for _, c := range cases {
		if FeeFromAge(c.age) != c.fee {
			t.Error("The judgment of fee is wrong\n")
		}
	}
}

慣れや好みの問題もあるかもしれませんが自分は下のテストの方が見やすく感じました。
上記の場合だと関数の中で新たに条件が追加された時にまた変数格納や条件を追加しなければなりませんが、下のテーブルドリブンテストだとデータセットを追加するだけでテスト可能です。

おわりに

テストを書く時には今後自分以外の人がテストを読んだり、拡張したりすることを考えて作成します。
そのためテーブルドリブンテストなら簡単に読めて拡張もし易いということでした。

Discussion