My Boundary As Much As I Experienced

React Testing Library 활용법 본문

FrontEnd/React

React Testing Library 활용법

Bumang 2023. 12. 16. 16:28

테스트에는 유닛테스트와 인터그레이션 테스트, e2e테스트가 있다.

유닛테스트는 jest, 인터그레이션 테스트는 react testing library로 많이 한다.

(jest로 인터그레이션 테스트도 가능하긴 함.)

 

CRA를 하면 react testing library와 zest를 기본적으로 깔아줌.

파일 이름 컨벤션은 App.test.js 식으로 많이 짠다.

 

 

in App.test.js

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

// learn More라는 텍스트가 있는지 확인하는 테스트
// 이걸 테스트할 필요가 있나?
test("renders learn More link", () => { // 맨처음은 식별자
  render(<App />);
  const linkElement = screen.getByText(/learn More/i);
  expect(linkElement).toBeInTheDocument(); //linkElement가 있기를 기대
});

 npm test하면 test할 수 있음

 

테스트 결과는 이렇게 나옴

 

 

실패하면 이렇게 뜸

 

 

3a in test

Arrange(데이터 설정, 테스트 환경 설정), Act(테스트되어야할 행동 설정), Assert(예상 행동을 테스트)

 

 

 

// helloWorld라는 텍스트가 있는지 없는지 알아보는 테스트
import { render, screen } from "@testing-library/react";
import Greeting from "./Greeting";

test("renders Hello world as a text", () => {
  // Arrange
  render(<Greeting />);

  // Act
  // ... Nothing

  // Assert
  const helloWorldEl = screen.getByText("Hello world", { exact: false }); // 기본값은 , { exact: true }
  expect(helloWorldEl).toBeInTheDocument(); // .not.toBeInTheDocument()도 가능함
});

예시) helloWorld라는 텍스트가 있는지 없는지 알아보는 테스트

 

 

 

 

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

describe("Greeting Component", () => { // test 쓰는거랑 비슷, Greeting Component로 카테고리화
  test("renders Hello world as a text", () => {
    // Arrange
    render(<Greeting />);

    // Act
    // ... Nothing

    // Assert
    const helloWorldEl = screen.getByText("Hello world", { exact: false }); // 기본값은 , { exact: true }
    expect(helloWorldEl).toBeInTheDocument(); // .not.toBeInTheDocument()도 가능함
  });
});

describe를 사용해서 그룹화해줄 수 있다.

 

 

 

import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import Greeting from "./Greeting";

describe("Greeting Component", () => {
  test("renders Hello world as a text", () => {
    // Arrange
    render(<Greeting />);

    // Act
    // ... Nothing

    // Assert
    const helloWorldEl = screen.getByText("Hello world", { exact: false }); // 기본값은 , { exact: true }
    expect(helloWorldEl).toBeInTheDocument(); // .not.toBeInTheDocument()도 가능함
  });

  test("renders It's good to see you as a text if button is not clicked yet", () => {
    render(<Greeting />);

    const longTimeNoSeeEl = screen.getByText("It's good to see you");
    expect(longTimeNoSeeEl).toBeInTheDocument();
  });

	// 3번 째: userEvent
  test("renders Long time no see if the button is clicked", () => {
    render(<Greeting />);

    // Act
    const buttonElement = screen.getByRole("button"); //HTMLTag로 선택
    userEvent.click(buttonElement);

    // Assert
    const changedTextEl = screen.getByText("Long time no see", { exact: false }); // 기본값은 , { exact: true }
    expect(changedTextEl).toBeInTheDocument();
  });
});

userEvent를 통해 virtual dom을 조작 후 원하는 결과를 테스트하는 방법

 

 

 

test("do not render It's good to see you if the button is clicked", () => {
    render(<Greeting />);

    // Act
    const buttonElement = screen.getByRole("button"); //HTMLTag로 선택
    userEvent.click(buttonElement);

    // Assert
    const originalTextEl = screen.queryByText("It's good to see you", { exact: false });
    // expect(originalTextEl).not.toBeInTheDocument(); 이것도 가능하긴 함
    expect(originalTextEl).toBeNull();
  });

실패해야 통과하는 테스트를 짜는 법

이럴 땐 queryByText로 텍스트를 지정해야된다. (getByText로 해버리면 텍스트를 찾을 수 없고 바로 테스트 실패를 반환한다.)

queryByText로 할 시 Boolean값으로 선택된다.

 

그리고 다른 컴포넌트가 복합적으로 존재하는 컴포넌트라 하더라도, 표면적으로 기능들을 사용할 수 있다면 테스트는 가능하다.

예를 들어 어떤 페이지에서 props.children에 있는 컴포넌트를 테스트하려면

그 컴포넌트를 따로 불러와서 해줘야되는게 아닌가 생각할 수 있는데,

실제 표면적으로 클릭만 가능한 상황이면 컴포넌트의 depth는 크게 중요치 않다.

 

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

describe("Async component", () => {
  test("renders posts if request succeeds", async () => { // async를 적어줘야한다.
    render(<Async />);

    // const listItemEls = screen.getAllByRole("listitem");
    // getAllByRole을 하면 비동기 요청이 완료되기도 전에 즉시 찾으려 할것이다.
    const listItemEls = await screen.findAllByRole("listitem", {}, {}); //find...는 비동기 요청이 성공할때까지 계속 시도한다.
    // ("찾을 속성", {exact(엄밀할지 안 할지)}, {timeout(몇초 기다릴지)})
    expect(listItemEls).not.toHaveLength(0);
  });
});

비동기 요청을 테스트하는 방법

비동기 함수이므로 async/await을 잘 써줘야 한다.

 

 

 

 

'FrontEnd > React' 카테고리의 다른 글

vite쓸꺼면 Jest는 쓰지말기  (1) 2023.12.20
jest 설치법  (0) 2023.12.20
React) useContext 사용법  (0) 2023.10.23
React) useReducer란?  (0) 2023.10.23
React) useRef란?  (1) 2023.10.22