React testing을 알아보자 (1)

Hoony·2022년 7월 1일
0

React Testing

목록 보기
1/2
post-thumbnail

💡 Testing을 하는 이유

Component의 개수가 몇개 되지 않을 때는 전체의 흐름을 파악한다거나
상황에 따라 코드를 수정하는것이 어려운 일이 아니다.

하지만, Applcation이 점점 커지면서 Component가 많아지게 되면
작성자 본인 뿐만아니라, 협업을 해야하는 동료들 또한
전체적인 흐름의 파악이 어려워지기도 한다.

파악이 어려워질수록 의도된 동작을 하지 않을 수 있고,
문제를 해결하기 위해 Debugging에 시간을 많이 써야할 수 있다.

Test 코드를 작성하게 되면

  • 의도한 동작을 확인할 수 있다.
  • 다양한 케이스를 고려해볼 수 있다.
  • Test를 위해서 Component와 Logic이 간결해진다.

더 많은 이점들이 있겠지만 결국 얻고자하는 것은
안정적인 소프트웨어를 만들 수 있다는 것이라 생각한다.

⭐ Testing Library

알아볼 라이브러리는 jest와 react-testing-library다.
mocha, jasmine과 같은 다른 testing 라이브러리도 있지만
이번 시리즈에서는 CRA로 프로젝트르 만들면 장착되어있는
라이브러리/프레임워크들에 대해서 알아보려고 한다.

jest

  • Testing Framework
  • Unit test를 위해 사용함
  • DOM의 노드들을 테스트
  • {file}.test.js / {file}.spec.js / [tests] directory를 알아서 찾아준다.

react-testing-library (RTL)

  • RTL은 DOM Testing Library(DTL) 위에 API를 추가하여 만들어진 라이브러리
  • DTL은 DOM을 Test하기위한 라이브러리임
  • 요소의 렌더링을 TEST

Enzyme vs RTL

Enzyme은 예전에 많이 썼지만, 최근에는 RTL을 더 많이 사용한다고 한다.
아래와 같은 차이점이 있다.

  • Enzyme - 구현 주도 테스트 ( Implementation Driven Test )
    • Props & State의 Flow를 고려하여 Testing 함
  • RTL - 행위 주도 테스트 ( Behavior Driven Test )

⭐ jest & testing Library 알아보기

jest file structure

  • describe ⇒ Test들을 묶어서 Block화
  • it ⇒ 개별 테스트
  • expect ⇒ 값을 테스트할 때 사용 ( matcher와 함께 사용 )
  • matcher⇒ 다른 방법으로 값을 테스트하기 위해 사용

아래 코드의 두번째 it에서 .toBe("applebanana")가 matcher이다.
expect에서 연산된 값과 다른 형태로 값을 넣어 확인할 수 있다.

describe("fruits test", () => {
	it("apple test", async () => {
		expect().matcher()
	})
	it("apple + banana", async() => {
		expect("apple" + "banana").toBe("applebanana")
	})
	...
});

Example for CRA App.test.js

아래 설명들은 CRA로 만든 프로젝트의 App.js를기반으로 한다.

  • App.js
    import logo from './logo.svg';
    import './App.css';
    
    function App() {
      return (
        <div className="App">
          <header className="App-header">
            <img src={logo} className="App-logo" alt="logo" />
            <p>
              Edit <code>src/App.js</code> and save to reload.
            </p>
            <a
              className="App-link"
              href="https://reactjs.org"
              target="_blank"
              rel="noopener noreferrer"
            >
              Learn React
            </a>
          </header>
        </div>
      );
    }
    
    export default App;
  • App.test.js
    • render

      • DOM에 Component Render하는 함수
      • query 함수와 utlity 함수를 가진 객체를 return 하지만,
        screen 객체로 대체하여 사용하는 것을 추천
    • screen
      - render함수의 return을 대체하여 사용하기 위해 사용
      - render함수는 destructuring 하여 값을 가져와야하는데
      screen은 query들을 다 가지고 있음

      import { render, screen } from '@testing-library/react';
      import App from './App';
      
      test('renders learn react link', () => {
        render(<App />);
        // const { getByText } = render(<App />);
        const linkElement = screen.getByText(/learn react/i);
        expect(linkElement).toBeInTheDocument();
      });

Query 함수들

  • 요소를 찾기 위해 사용하는 함수를 의미한다.
  • get / find / query 를 적절하게 사용 해야한다.
  • 기본적으로는 1개를 찾아 반환한다.
  • 2개 이상을 찾을 때는 {get|find|query}AllBy 형태로 사용한다.

get

screen.getByText(/hi react/i); // Error 

query

  • 요소가 없으면 null
  • 2개 이상이면 Error ( queryBy )
screen.queryBy(/hi react/i); // Error
screen.queryBy(/hi/i); // null

find

  • 요소가 발견되면, Promise를 반환
  • 요소가 없거나, 1000ms후에 둘이상 요소가 발견되면 Reject됨
  • 기다릴 수 있는 유일한 쿼리
  • getBy + waitFor = findBy
    • waitFor ⇒ 일정 기간동안 기다려야할 때 사용
screen.findByText(/Learn React/i);
await waitFor(() => { screen.getByText(/Learn React/i) })

⭐ testing과 관련된 eslint & prettier Setting

VScode 에서 Extension 설치

  • ESLint
  • Prettier - Code formatter

관련 플러그인 설치

yarn add eslint-plugin-testing-library eslint-plugin-jest-dom --dev

.eslintrc.json 적용

App.test.js 에서 잘못된 부분들을 잡아주는것을 확인할 수 있다.

{
    "extends": [
        "react-app",
        "react-app/jest",
        "pulgin:testing-library/react",
        "plugin:jest-dom/recommended"
    ],
    "plugins": [
        "testing-library",
        "jest-dom"
    ]
}
profile
아는 만큼 보인다

0개의 댓글