React testing을 알아보자 (2)

Hoony·2022년 7월 9일
0

React Testing

목록 보기
2/2

TDD (Test Driven Development) 란?

TDD란 요약하자면 Test Code먼저 작성하는 개발방법이라 할 수 있다.

Testing을 하지 않고 개발을 하면 아래와 같이 코드를 작성한다.

  1. 어떻게 컴포넌트를 구현하지?
  2. 구현 해볼까?
  3. 문제가 있네?
  4. 고쳐보자. ( 3 -> 4 반복 )
  5. 완료.

Test Code를 먼저 작성하면 아래와 같이 작성한다.

  1. 어떻게 컴포넌트를 구현하지?
  2. Test code를 작성해볼까?
  3. Test code를 통과하는 컴포넌트를 구현해보자.
  4. 완료.
  • Test Code가 있기 때문에, 코드에 대한 안정감이 생긴다.
  • Debugging할 시간이 줄어들어, 총 개발 시간을 줄일 수 있다.
  • 유지보수에 용의하다. 신규 기능을 추가할 때 기존 기능과의 충돌체크가 쉬워진다.

이 외에도 다양한 장점들이 있긴하다.

하지만, 경우에 따라서 초반에 개발 시간이 더 들어갈 수 있으며
협업하는 환경이라면 모두가 Testing 코드에 익숙해야 한다.

fireEvent API vs userEvent API

fireEvent와 userEvent는 유저의 인터렉션을 포함한 Testing하기 위한 API이다.
결론적으로, userEvent API 를 활용하는 것이 옳다.

userEvent는 fireEvent를 기반으로 만들어졌는데
userEvent는 Element의 Type에 따라 좀 더 적절한 Event가 호출된다.
fireEvent는 button을 click하여도, focus가 안되는 등 기능에만 집중되어있다.

@testing-library에 포함되어 있으며 아래와 같이 import된다.

import { fireEvent } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

다음과 같이 사용할 수 있다.
어떠한 button이 있다고 하자.

const Counter = () => {
  const [counter, setCounter] = useState(0);
  return (
      <p data-testid="counter">{counter}</p>
      <button data-testid="plus-btn"
        onClick={() => setCounter(counter + 1)}>
      +</button>  
  )  
}

test code에서 두 API는 다음과 같이 사용한다.

test("+ button pressed, counter changed 1", () => {
  	render(<Counter />);
	const btnElement = screen.getByTestId('plus-btn');
  	const numElement = screen.getByTestId('counter');
  	// fireEvent.click(btnElement);
  	userEvent.click(btnElement);
  	expect(numElement).toHaveTextContent(1);
})

Multiple expect in One test function

하나의 test함수에 여러개의 expect를 하면 어떻게 될까?
결론적으로는 가능하다.

예를 들어, 어떤 버튼을 누르면 3개의 버튼이 disabled 되는 상황을 test 하면 정상적으로 동작은 한다.

test("diabled button pressed, all buttons disabled", () => {
  	render(<App />)
  	const disabledElement = screen.getByTestId('disabled-button');
  	userEvent.click(disabledElement);
  
  	const aBtn = screen.getByTestId('a-btn');
  	const bBtn = screen.getByTestId('b-tn');
  	const cBtn = screen.getByTestId('c-btn');
  
  	expect(aBtn).toBeDisabled();
  	expect(bBtn).toBeDisabled();
  	expect(cBtn).toBeDisabled();
})

상황에 따라 변하지 않으면서 단순한 것들은 묶어서 처리할 수 있다.
하지만, 가급적 나누어서 처리하는 것이 클린한 코드가 아닐까?
협업하는 환경에서는 판단 하는기준이 달라질 수 있기 때문에
1 function 1 test가 convention으로 적합할 것 같다는 생각이다.

profile
아는 만큼 보인다

0개의 댓글