使用 Jest test.each 撰寫多個測試情境

使用 Jest test.each 撰寫多個測試情境

·

1 min read

前陣子在替typescript邏輯寫單元測試需要多種test case來驗證.正當寫多個test() function覺得麻煩時,突然想到jest是否有提供像C# NUnit TestCase attribute的功能,能將多個test case透過function parameter帶入同一個測試function呢?

[TestCase(12, 3, 4)]
[TestCase(12, 2, 6)]
[TestCase(12, 4, 3)]
public void DivideTest(int n, int d, int q)
{
    Assert.AreEqual(q, n / d);
}

查了一下發現真的有類似的API, 可以透過test.each這個介面將test cases以陣列, 物件 或table的形式帶入

test.each([
  [1, 1, 2],
  [1, 2, 3],
  [2, 1, 3],
])('.add(%i, %i)', (a, b, expected) => {
  expect(a + b).toBe(expected);
});
test.each([
  {a: 1, b: 1, expected: 2},
  {a: 1, b: 2, expected: 3},
  {a: 2, b: 1, expected: 3},
])('.add($a, $b)', ({a, b, expected}) => {
  expect(a + b).toBe(expected);
});
test.each`
  a    | b    | expected
  ${1} | ${1} | ${2}
  ${1} | ${2} | ${3}
  ${2} | ${1} | ${3}
`('returns $expected when $a is added $b', ({a, b, expected}) => {
  expect(a + b).toBe(expected);
});

從範例中也看到可以使用 %$的方式將參數帶進test description

個人是習慣用物件的方式, 可以透過property描述參數名稱, 比較語意化.以下是我撰寫的測試案例

import {groupArray} from "./array";

describe('groupArray', () => {
  test.each(
    [
      {inputArr:[1,1,1,1], groupNum: 1, expected: [[1],[1],[1],[1]]},
      {inputArr:[1,1,1,1], groupNum: 2, expected: [[1,1],[1,1]]},
      {inputArr:[1,1,1,1], groupNum: 3, expected: [[1,1,1],[1]]},
      {inputArr:[1,1,1,1], groupNum: 4, expected: [[1,1,1,1]]},
      {inputArr:[1,1,1,1], groupNum: 5, expected: [[1,1,1,1]]},
      {inputArr:['a','b','c','d'], groupNum: 2, expected: [['a','b'],['c','d']]},
    ]
  )
  ('should return $expected when input array is $inputArr and groupNum is $groupNum', ({inputArr, groupNum, expected}) => {
      expect(groupArray(inputArr as any[],groupNum)).toEqual(expected);
  });
});

實際執行測試可以看到各個參數皆為獨立的test case, 可以看到是哪個test case assert fail 但如果參數本身是陣列或物件的話印出來就不這麼語意化, 可能要試試看override toString()可不可以印出語意化的文字

Screen Shot 2022-07-19 at 10.09.38 PM.png

希望可以幫助大家節省寫測試的時間.