Goでユニットテストの書き方① 基礎編
testing.Tのポインタを引数に取る関数を定義する
ベンチマークテストのことを先に調べてからユニットテストを調べているのもアレだが、Goでユニットテストを書くときはtesting.Tのポインタを引数に取る関数を定義すれば良いらしい。
assertなんちゃら といったメソッドは無い: t.Error(), t.Errorf()を使う
PythonやJavaのユニットテストライブラリに慣れた身としては、まずアサーションの実行には「Error」や「Errorf」という名前のメソッドを使うルールに混乱した。
ちゃんと「Fail」というメソッドもあるので、最初こっちを使うのだろうと思ったが、どうやらこれはPythonのunittest.TestCase.fail()に相当する(=とにかくテストを失敗させるメソッド、アサーション無し)もののようだ。
簡単な例を示すとこんな感じ。
[foo/main_test.go]
package foo import "testing" func TestFoo(t *testing.T){ var result int var err error result, err = Foo("1") if result, error = Foo("1"); err != nil { t.Errorf("処理に失敗しました: %v", err) } if result != 10 { t.Errorf("結果が不正です: %v != 10", result) } }
非公開モジュールのテストをするためにアプリケーションコードと同じパッケージに所属させる
小文字で名前が始まるモジュールはパッケージの外からアクセスできないので、それらのテストを書く場合はテスト対象と同じパッケージを宣言する。
ひとつのテストケースの中で複数のアサーションをやっても別々に出力してくれる
感心したのが、testing.Tはt.Errorfを同じ関数(=テストケース)の中で複数出力しても処理は続行される点だ。
Pythonならば、assertなんちゃらメソッドを呼んで期待値と結果が異なれば、即座にそのテストケースは打ち切りになる。
import unittest class FooTest(unittest.TestCase): def test(self): self.assertEqual(1, 0) # ここでテスト失敗、処理は打ち切られる。 self.assertEqual(2, 2) # ここは通らない
しかし、Goの場合はt.Error, t.Errorfが標準出力にテストの失敗を出してくれるだけで、処理は続行される。
import "testing" func TestFoo(t *testing.T){ if 1 != 0 { t.Error("結果が不正です: 1 != 0") // ここで処理は止まらない } if 2 != 1 { t.Error("結果が不正です: 2 != 1") // こっちもテストしてくれる } }
[処理結果]
--- FAIL: TestFoo (0.00s) sample_test.go:7: 結果が不正です: 1 != 0 sample_test.go:11: 結果が不正です: 2 != 1 FAIL FAIL github.com/oyakata/tokyo/err 0.007s
このように、ちゃんとTestFooの中で別々の検証と判るよう整形してくれることに感銘を受けた。