본문 바로가기
공부

[rtl] 테스트 코드

by jaeeedev 2023. 3. 19.

TDD

코드 작성 전에 테스트코드를 작성하고

코드 작성 후에 통과 시키기

 

왜 TDD?

테스트를 작성하는것이 프로세스에 자연스럽게 통합되도록

원하는 대로 동작하는지를 확인할 수 있음

 

jest와 rtl

rtl은 가상 돔을 렌더링하고 요소를 검색하고 가상 돔과 상호작용하는 역할

그리고 여기서 테스트 러너가 필요한데 그게 제스트

에러가 있어야 걸리는 구조라 빈 테스트면 통과됨, throw Error 해도 걸림

 

유닛 테스트

코드의 한 부분을 테스트, 다른 유닛과의 상호작용을 고려하지 않음

코드(함수)의 테스트는 가능해도 사용자 관점의 테스트를 뜻하지는 않음

리팩토링 시 동일한 동작이라도 테스트에서 걸릴 수 있음

 

통합 테스트

여러 유닛의 상호작용을 테스트

 

기능 테스트

일반적인 함수가 아닌 소프트웨어의 동작을 테스트(좀 더 전체적인 느낌)

코드가 아닌 행동(동작)을 테스트하는 것

디버깅이 어려울 수 있음

RTL은 기능 테스트 식으로 테스트하기를 권장

 

E2E테스트

실제 브라우저가 필요하고 서버가 필요

단언문에서 실패하면 다음 테스트를 수행하지 않고 바로 멈춤

 

테스트 코드 예시

import { render, screen, fireEvent } from "@testing-library/react";

test("button has correct initial color", () => {
  render(<App />);

  const colorButton = screen.getByRole("button", {
    name: "Change to Midnight Blue",
  });

  expect(colorButton).toHaveStyle({
    backgroundColor: "MediumVioletRed",
  });

  fireEvent.click(colorButton);

  expect(colorButton).toHaveStyle({ backgroundColor: "MidnightBlue" });
  expect(colorButton).toHaveTextContent("Change to Medium Violet Red");
});

버튼 컴포넌트를 테스트한다고 치면 어떤 클래스네임을 가진 버튼을 선택하는 방식이 아니라 어떤 텍스트를 가진 버튼(getByRole로 기능을 확인)인지를 체크하여 동작시킨다.

최초 색상,텍스트 확인 - 클릭(`fireEvent`) - 변경된 색상, 텍스트 확인

이런 구조라서 시나리오를 쓰듯 테스트 할 수 있다.

fireEvent와 user-event의 차이

  • fireEvent는 DOM의 이벤트를 디스패치
  • user-event는 모든 상호작용을 시뮬레이션(좀 더 사용자 관점), promise를 반환

user-event

import userEvent from "@testing-library/user-event";

test("...", async () => {
  const user = userEvent.setup();

  await user.click(element);
});

user-event를 사용하기 위해서는 setup 메서드를 사용해 유저 객체를 만들고
객체 내부의 이벤트 메서드를 사용해야 한다.
그리고 이 이벤트들은 promise를 반환하기 때문에 await을 꼭 써주어야 한다(당연히 테스트의 콜백 함수도 async 함수여야 함)

getBy와 queryBy의 차이점

getBy는 일치하는 요소가 없거나 여러개인 경우 오류를 발생시킨다.
반면에 queryBy는 일치하는 요소가 없으면 null을 반환한다. 특정 이벤트(호버)가 발생했을 때만 나타나는 팝업같은 요소를 테스트할 때 사용한다.

댓글