🧪
DartでJestのeachっぽくParameterized Testする
DartでJestのeachのようにParameterized Testする方法がなかったので自前で実装してみました。
Parameterized Testとは
Parameterized Testとは同じテストロジックを複数の異なる入力で実行することを可能にする手法です。
同じテストロジックを複数のテストデータセットで実行できるため、冗長なテストコードの記述を避けられ、コードの可読性と保守性が向上します。
Jestでは以下のようにeach
を使ってParameterized Testを実装することができます。
test.each([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('.add(%i, %i)', (a, b, expected) => {
expect(a + b).toBe(expected);
});
作ったutil関数
import 'package:meta/meta.dart';
void Function(void Function(T param) test) each<T>(
String description, List<T> params) =>
(Function(T) test) => group(description, () => params.forEach(test));
かなり短い関数ですが、少しこだわっています。
こだわりポイント
- 関数をカリー化することで、Jestの
each
と同様にテストデータとテストロジックの分離ができる - Generics(総称型)を使うことで、パラメーターの型をサジェストしてくれる
-
@isTestGroup
メタデータアノテーションをつけることで、テストグループとしてVSCodeが認識してくれるため、CodeLensのDebug
ボタンやTesting機能が使えます。
※ ちなみに、この@isTestGroup
をつける場合、関数の第一引数はテストの説明を設定する必要があるため、自作したeach
関数の第一引数はString description
になっています。
使い方
例として、2つの引数を受け取り、その積を返す関数 multiply
のテストを行います。
multiply.dart
int multiply(int a, int b) {
return a * b;
}
multiply_test.dart
void main() {
each("multiply", [
// 名前付きパラメータのRecordを使うと、型の補完もしてくれて可読性も良いのでおすすめです
(a: 0, b: 0, expected: 0),
(a: 1, b: 1, expected: 1),
(a: 2, b: 2, expected: 4),
(a: 3, b: 3, expected: 9),
])((param) {
test('${param.a} * ${param.b} = ${param.expected}', () {
expect(multiply(param.a, param.b), param.expected);
});
});
}
Discussion