🧪

DartでJestのeachっぽくParameterized Testする

2024/04/28に公開

DartでJestのeachのようにParameterized Testする方法がなかったので自前で実装してみました。

https://gist.github.com/ikoamu/a2b3426b55bd9ac943ff3cefb09b2152

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になっています。

https://api.flutter.dev/flutter/meta/isTestGroup-constant.html

使い方

例として、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