【Jest】「test.each」や「it.each」でテーブル駆動テストをする方法

この記事ではJestのtest.eachit.eachを用いてテーブル駆動テストをする方法を説明しています。サンプルコードを用いて分かりやすく説明するように心掛けています。ご参考になれば幸いです。

Jestの「test.each」や「it.each」の使い方

Jestのtest.eachit.eachを用いると、テーブル形式のデータを使って複数のテストケースを簡単に作成することができるようになります。異なる入力に対して、同じテストを繰り返し行いたい時に便利です。

test.eachit.eachの構文を以下に示します。

構文

// test.eachを使う場合
test.each(table)(name, fn, [timeout]);
// it.eachを使う場合
it.each(table)(name, fn, [timeout]);
  • table: テストパラメータを格納した配列
  • name: テストタイトル(テストパラメータを含むことができる)
  • fn: テスト関数(tableの各行のパラメータを引数として受け取る)
  • timeout: テストがタイムアウトするまでの時間をミリ秒単位で指定するオプション

test.eachit.eachのどちらを使用しても構いません。

では、実際にtest.eachを用いた簡単なサンプルコードを見てみましょう。以下に示したサンプルコードでは単純に足し算をテストしています。tableの箇所に関数の引数や期待値を記述します。このテストでは3回テストを繰り返しています。例えば、1回目のテストでは、関数の引数aに1、引数bに2、引数expectedに3を与えてテストしています。

test.each([
  [1, 2, 3], // 1回目のテスト
  [2, 3, 5], // 2回目のテスト
  [3, 4, 7], // 3回目のテスト
])('%iと%iを足すと%iになるか', (a, b, expected) => {
  expect(a + b).toBe(expected);
});

テスト結果

 PASS  ./sample01.test.js
  √ 1と2を足すと3になるか (2 ms)
  √ 2と3を足すと5になるか
  √ 3と4を足すと7になるか

Test Suites: 1 passed, 1 total
Tests:       3 passed, 3 total
Snapshots:   0 total
Time:        0.531 s
Ran all test suites.

このように、配列によってテストパラメータを指定することができるようになり、Jestはその配列の個数分だけテストを繰り返し実行してくれます。また、テストタイトルには、printfの書式に従うパラメータを使用することができ、上記のサンプルコードでは、%i(整数)を使用しています。

オブジェクトの形式でのtest.each

オブジェクトの形式でテストを書くこともできます。

test.each([
  { a: 1, b: 2, expected: 3 }, // 1回目のテスト
  { a: 2, b: 3, expected: 5 }, // 2回目のテスト
  { a: 3, b: 4, expected: 7 }, // 3回目のテスト
])('$aと$bを足すと$expectedになるか', ({ a, b, expected }) => {
  expect(a + b).toBe(expected);
});

テスト関数の引数にはオブジェクトが渡されるので、オブジェクトの分割代入を用いて、各パラメータ(a, b, expected)を受け取っています。また、テストタイトルにパラメータを使う場合には、$パラメータ名でアクセスすることができます。

タグ付きテンプレートリテラルを使用したtest.each

タグ付きテンプレートリテラルを用いて、テストを書くこともできます。タグ付きテンプレートリテラルを用いると、各テストのテストパラメータが視覚的に区別しやすくなります。

タグ付きテンプレートリテラルを用いる場合、test.eachit.eachの構文は以下のようになります。

構文

// test.eachを使う場合
test.each`table`(name, fn, [timeout]);
// it.eachを使う場合
it.each`table`(name, fn, [timeout]);
  • table: タグ付きテンプレートリテラルで記述したテストパラメータ
  • name: テストタイトル(テストパラメータを含むことができる)
  • fn: テスト関数(tableの各行のパラメータを引数として受け取る)
  • timeout: テストがタイムアウトするまでの時間をミリ秒単位で指定するオプション

では、実際にtest.eachでタグ付きテンプレートリテラルを用いた場合のサンプルコードを見てみましょう。以下に示したサンプルコードでも単純に足し算をテストしています。

test.each`
  a    | b    | expected | comment
   |  |      | ${'Test 1'}
   |  |      | ${'Test 2'}
   |  |      | ${'Test 3'}
`('[$comment] $aと$bを足すと$expectedになるか',({ a, b, expected, comment }) => {
    expect(a + b).toBe(expected);
  }
);

テスト結果

 PASS  ./sample01.test.js
  √ [Test 1] 1と2を足すと3になるか (2 ms)
  √ [Test 2] 2と3を足すと5になるか
  √ [Test 3] 3と4を足すと7になるか (1 ms)

Test Suites: 1 passed, 1 total
Tests:       3 passed, 3 total
Snapshots:   0 total
Time:        0.535 s, estimated 1 s
Ran all test suites.

tableの1行目にはパラメータ名を指定します。テスト関数の引数にはオブジェクトが渡されるので、オブジェクトの分割代入を用いて、各パラメータ(a, b, expected, comment)を受け取っています。ただし、注意点としては、string型でも${}で囲まなければいけないので注意してください。

また、テストタイトルにパラメータを使う場合には、$パラメータ名でアクセスすることができます。