본문 바로가기
source-code/FrontEnd

[jest] test.each를 통해 여러 입력값 테스트 간결하게 구현하기

by mattew4483 2024. 6. 13.
728x90
반응형

Backgrounds

동일한 테스트를, 입력값만 바꾸어서 실행해야 할 때가 있습니다.
데이터를 특정 형태로 변환하는 함수들이 대표적인 경우겠죠.
 
예를 들어, 입력받은 ms를 시간과 분 으로 분리하는 함수가 있습니다.

import { convertMsToHoursAndMinutes } from '@/utils/time';

  it('ms => 시간/분 변환 함수 동작 테스트', () => {
    const ms = 1800000; // 30분

    const { hours, minutes } = convertMsToHoursAndMinutes(ms);

    expect(hours).toBe(0);
    expect(minutes).toBe(30);
  });

 
1800000ms(30분)을 입력받으면, 0시간 30분 을 반환하는지 테스트 코드를 작성했습니다.
 
위 테스트를 통과했을 때... 해당 함수를 신뢰하고 사용할 수 있을까요?
물론 그럴 수도 있겠지만. 아마 아닐 것입니다. 
 
적어도 아래와 같은 케이스에 대한 테스트 정도는 작성되어 있어야 하겠죠!

  • 1시간 이하의 ms 입력 시, 정상 동작 하는지 
  • 1시간~24시간 이내의 ms 입력 시, 정상 동작 하는지
  • 24시간을 초과하는 ms 입력 시, 정상동작 하는지

시간을 변환한다는 특성상,
데이터 경곗값(0시간, 24시간)에 대한 테스트가 존재해야만, 코드 사용자가 해당 함수를 신뢰할 수 있을 것입니다.
 

Problems

테스트를 추가하면, 이런 형태가 됩니다.

  import { convertMsToHoursAndMinutes } from '@/utils/time';

  it('ms => 시간/분 변환 함수 동작 테스트', () => {
    const ms1 = 1800000; // 30분

    const { hours1, minutes1 } = convertMsToHoursAndMinutes(ms1);

    expect(hours1).toBe(0);
    expect(minutes1).toBe(30);
    
    const ms2 = 5400000; // 1시간 30분
    const { hours2, minutes2 } = convertMsToHoursAndMinutes(ms2);

    expect(hours2).toBe(0);
    expect(minutes2).toBe(30);    
    
    
    const ms3 = 9060000; // 24시간 10분
    const { hours3, minutes3 } = convertMsToHoursAndMinutes(ms3);

    expect(hours3).toBe(0);
    expect(minutes3).toBe(30);     
  });

 
물론 테스트는 정상적으로 실행되지만,
동일한 테스트가 입력값만 변경된 채 계속해서 반복되는 모습을 볼 수 있습니다.
 
또한 같은 it 테스트 scope내에 존재하다 보니,
입력값과 반환값에 대한 변수명도 계속해서 다르게 유지해야 한다는 점이 굉장히 번거롭죠.
 
하지만 가장 큰 문제점은... → 해당 테스트의 의도를 직관적으로 파악하기 힘들다는 점!
 

Solutions

 test.each 구문을 통해, 다양한 입력값에 대한 동일 테스트를 간결하게 구현할 수 있습니다.
(이를 파라미터화 테스트parameterized 라고 합니다)
 
https://jestjs.io/docs/api#testeachtablename-fn-timeout

Globals · Jest

In your test files, Jest puts each of these methods and objects into the global environment. You don't have to require or import anything to use them. However, if you prefer explicit imports, you can do import {describe, expect, test} from '@jest/globals'.

jestjs.io

 
위 테스트의 경우, 아래와 같이 수정할 수 있습니다!

  import { convertMsToHoursAndMinutes } from '@/utils/time';

  it.each([
    { ms: 1800000, hours: 0, minutes: 30 }, // 30분
    { ms: 5400000, hours: 1, minutes: 30 }, // 1시간 30분
    { ms: 9060000, hours: 24, minutes: 10 }, // 24시간 10분
  ])(
    'returns expected $hours and $minutes, when $ms given',
    ({ ms, hours, minutes }) => {
      const results = convertMsToHoursAndMinutes(ms);
	
      expect(results.hours).toBe(hours);
      expect(results.minutes).toBe(minutes);
    },
  );

 
주어진 ms를 hours와 miniutes로 변환한다는 의도가 한결 명확해진 모습!
더불어 추후 테스트 케이스를 추가하고 싶을 때도, 테스트 구현을 건드리지 않은 채 데이터만 손쉽게 추가해 줄 수 있겠죠.

728x90
반응형