はじめに
Unitテストを書くとき、いろいろなテストケースで書く場合テストコードが煩雑になりがちなことがあるかと思います。
例えば、ログイン状態だとある値を返すけど、非ログイン状態だとnullで返すメソッドのテストをするときや、朝昼夜など時間帯によって結果が変わるようなメソッドの場合など様々なケースでテストを書きたいときはよくあります。
そのときに役立つのがGolangの界隈にあるTableDrivenTestsです。
TableDrivenTestsとは、テストケースをテーブル状に宣言しておいて、あとはそのテストケースを順番にテストコードのパラメータとして流すだけで、可読性も高く網羅的に比較的簡単にテストをかけるようにする手法です。
やっていき
言葉だとイマイチわからないと思うので、実際に紹介していきます。
用意するもの
google.devが公開しているtupleというpackageを使います。
その名の通りTupleのデータ構造を定義できるようになります。
書いてみる
今回はTableDrivenTestsの紹介なので、テストの内容は適当です。
ログイン済みかどうかの isAuthenticated
がtrueかfalseかで挙動が変わるint? sample()
のテスト書きたいとします。
tuple
packageを使ってるので、Tuple
型を使えます。 Tuple7
まで対応しているようです。
今回はTuple2
を使って、item1
にログイン済みかどうかのboolとitem2
に期待しているmatcherを格納しています。
void main() {
// テストケースのテーブル定義
final testCases = [
Tuple2(true, 1),
Tuple2(false, null),
];
// テストケースを順番に実行
for (final testCase in testCases) {
test('authenticated is ${testCase.item1}', () {
expect(sample(testCase.item1), testCase.item2);
});
}
}
// サンプル用のメソッド
int? sample(bool isAuthenticated) {
return isAuthenticated ? 1 : null;
}
今回は純粋にboolによる挙動のみのテストをサンプルに書きましたが、複数のboolで挙動が変わるテストもTuple3
を使ってテーブルのパラメータを増やせばかけますし、enumで挙動が変わるものなども可読性高くかけそうです。
どんなテストケースに対応しているかも、テーブル定義を見れば一覧で見れるので、メンテナンス性も高いと感じています。
Dartの今後
今回は、tuple
というpackageを使ってTableDrivenTestsを実現しましたが、この機能がDartの言語機能として検討されています。
https://github.com/dart-lang/language/issues/68
そのうちpackageに頼らなくても良くなるかもしれません。
おわりに
複雑なコードのUnitテスト書きたい場合、既存で複雑なテストケースによって煩雑なテストコードになっている場合、ぜひTableDrivenTestsを検討してみてください。