🧪
Jest each修飾子を使用したParameterized Test
Jestを使用してテストを書いていると、パターン化されたテストを書く場合があります。
そのような場合には、each
修飾子を使用することで、パラメータ化されたテストを書くことができます。
each修飾子について
each
修飾子は、配列を引数として受け取り、その配列の要素を使ってテストを実行できます。
書き方は3通りあります。それぞれの書き方について説明します。
ここでは、以下のような関数をテストすることを考えます。みなさんご存知のFizzBuzzです。
3で割り切れる場合はFizz
、5で割り切れる場合はBuzz
、3と5で割り切れる場合はFizzBuzz
、それ以外の場合はその数値を文字列に変換して返します。
type ResultFizzbuzz = (num: number) => string
const resultFizzbuzz: ResultFizzbuzz = (num: number) => {
const isFizz = num % 3 === 0
const isBuzz = num % 5 === 0
const isFizzBuzz = isFizz && isBuzz
if (isFizzBuzz) return 'FizzBuzz'
if (isFizz) return 'Fizz'
if (isBuzz) return 'Buzz'
return `${num}`;
}
Array of objects
オブジェクトの配列を引数として受け取ります。この場合、オブジェクトのプロパティを使ってテストを実行できます。
他の書き方と比べて冗長な書き方ですが、型推論がきくため、型安全なテストを書くことができます。
it.each([
{ num: 1, expected: '1' },
{ num: 2, expected: '2' },
{ num: 3, expected: 'Fizz' },
{ num: 5, expected: 'Buzz' },
{ num: 15, expected: 'FizzBuzz' },
])('FizzBuzz Test', ({ num, expected }) => {
expect(resultFizzbuzz(num)).toBe(expected)
})
Array of arrays
配列の配列を引数として受け取ります。この場合、配列の要素を使ってテストを実行できます。
オブジェクト配列と比べてスムーズに書くことができます。
it.each([
[1, '1'],
[2, '2'],
[3, 'Fizz'],
[5, 'Buzz'],
[15, 'FizzBuzz'],
])('FizzBuzz Test', (num, expected) => {
expect(resultFizzbuzz(num)).toBe(expected)
})
配列を変数に切り出した場合
注意点として、配列を変数に切り出した場合うまく型推論ができずエラーを吐きます。
その場合は、型を明示的に指定することでエラーを回避できます。
// NG: 型推論がきかないためエラー
const table = [
[1, '1'],
[2, '2'],
[3, 'Fizz'],
[5, 'Buzz'],
[15, 'FizzBuzz'],
]
// OK: 型を明示的に指定
const table: Array<[number, string]> = [
...
]
// OK: as constを使用しても回避できる
const table = [
...
] as const
Template literals
テンプレートリテラルを引数として受け取ります。この場合、テンプレートリテラルのプレースホルダを使ってテストを実行できます。
テーブルの見た目がわかりやすくなり、視認性が向上します。
it.each`
num | expected
${1} | ${'1'}
${2} | ${'2'}
${3} | ${'Fizz'}
${5} | ${'Buzz'}
${15} | ${'FizzBuzz'}
`('FizzBuzz Test', ({ num, expected }) => {
expect(resultFizzbuzz(num)).toBe(expected)
})
さいごに
each
修飾子を使用することで、パラメータ化されたテストを書くことができます。
パターン化されたテストに使用することで、テストの冗長性を減らし、視認性を向上させることができます。
参考
Discussion