#6 React TDD 기본

김민성·2023년 5월 17일
0
post-thumbnail

테스트 주도 개발(TDD)란 무엇인가?

Test Driven Development란?

실제 코드를 작성하기 전에 테스트 코드를 먼저 작성합니다.
테스트 코드를 작성한 후, 그 테스트 코드를 Pass 할 수 있는 실제 코드를 작성한다.


TDD를 하면 좋은 점

  1. TDD를 하므로 인해 많은 기능을 테스트하기에 소스 코드에 안정감이 부여된다.
  2. 실제 개발하면서 많은 시간이 소요되는 부분은 디버깅 부분이기에 TDD를 사용하면 디버깅 시간이 줄어들고 실제 개발 시간도 줄어든다.
  3. 소스 코드 하나하나를 더욱 신중하게 짤 수 있기 때문에 깨끗한 코드가 나올 확률이 높다.

React Testing Library 란?

Create React App로 리액트 앱을 생성하면 기본적으로 테스팅 할 때 React Testing Library를 사용하는 것을 볼 수 있다. 그럼 이 React Testing Library가 무엇일까?

React Testing Library란 무엇일까?


<참고(공식문서)>
[링크텍스트](https://testing-library.com/docs/react-testing- library/intro/)


  • React Testing Library는 React 구성 요소 작업을 위한 API를 추가하여 DOM Testing Library 위에 구축된다.
  • DOM Testing Library란 Dom 노드(Node)를 테스트하기 위한 매우 가벼운 솔루션이다.
  • Create React App으로 생성된 프로젝트는 즉시 React Testing Library를 지원한다. 그렇지 않은 경우 다음과 같이 npm을 통해 추가할 수 있다.
npm install --save-dev @testing-library/react

리액트 컴포넌트를 테스트하는 가벼운 솔루션이다.


React Testing Library는 에어비앤비에서 만든 Enzyme을 대처하는 솔루션이다.
Enzyme이 구성 요소의 구현 세부 정보를 테스트하는 대신, React Testing Library는 개발자를 React 애플리케이션의 사용자 입장에 둔다.


위의 이미지를 통해 예를 들어보면, 2개의 컴포넌트가 있을 때, a컴포넌트에서 b컴포넌트로 데이터를 전달할 때 prop를 통해 전달한다. 그리고 컴포넌트 안에서 state을 이용해 어떠한 기능을 구현하거나, 데이터의 흐름을 가져온다.

그래서 Enzyme을 사용할 때에는 구현 주도 테스트이기 때문에 prop이 어떠한 식으로 교환되는지, state은 어떠한 식으로 흘러가게 되는지 그러한 구현을 주도해서 테스트를 하게 된다.

하지만 React Testing Library을 사용할 때에는 행위 주도의 어떠한 기능이 있고 어떠한 기능이 잘 작동하는지에 대해 더 중점적으로 테스트하게 된다.

<p>
Edit <code>src/App.js</code> and save to
reload....
</p>

구현 주도 테스트에서는 위의 UI를 테스트할 때 주로 'p 태그'가 쓰였고 Edit 등의 문자가 들어갔다는것을 테스트한다. 그래서 만약 'p 태그'를 'h2 태그'로 바뀌면 에러가 날 것이다.

하지만 행동 주도 테스트에서는 사용자의 입장에서 테스트 하기에 'p 태그'가 쓰이던 'h3 태그'가 쓰여서 글을 표현하는지가 중요한지 보다 어떠한 이벤트를 발생시켰을 때 화면이 어떻게 변화되는지와 같은 테스트가 더 주를 이루게 된다.

이렇게 가볍게 알아보고 실제 사용하면서 더 자세히 알아보자.

Jest 란?

Jest란 무엇인가요?

  • FaceBook에 의해서 만들어진 테스팅 프레임 워크입니다.
  • 최소한의 설정으로 동작하며 Test Case 를 만들어서 어플리케이션 코드가 잘 돌아가는지 확인해줍니다.
  • 단위 (Unit) 테스트를 위해서 이용합니다.

Jest 시작하기

  1. Jest 라이브러리 설치
npm install jest --save-dev
  1. Test 스크립트 변경
"test" : "jest" or "jest --watchAll 
  1. 테스트 작성할 폴더 및 파일 기본 구조 생성

원래는 위와 같이 설치를 해주어야 하지만, 하지만 create-react-app으로 설치하면 Jest도 설치되기에 따로 해주지 않아도 된다.

Jest가 하는 일

Jest는 Test 파일을 찾아준다. 우리는 어떠한 파일에다가 Testing Case들을 만들어두는데, 이 때, Jest가 그 파일을 찾아준다. 파일 이름에 test나 spec을 넣거나, 폴더 이름을 tests라고 해두고 안에 파일을 넣으면 Jest는 test를 위한 파일이라고 인식하고 찾아준다.

Jest 파일 구조 및 사용법

Jest 파일 구조

describe

여러 관련 테스트를 그룹화하는 블록을 만든다.

test ( = it )

개별 테스트를 수행하는 곳. 각 테스트를 작은 문장처럼 설명한다.

이렇게 사과, 바나나와 같이 관련된 것들을 그룹화하는 것을 describe라고 하고, 사과, 바나나는 test(=it)이다.

expect

expect 함수는 값을 테스트할 때마다 사용된다. 그리고 expect 함수 혼자서는 거의 사용 되지 않으며 matcher와 함께 사용된다.

matcher

다른 방법으로 값을 테스트 하도록 "matcher"를 사용한다.

여기서 toBe는 matcher이다. expect한 것을 test해주는 것이 matcher이다. 즉, 2+2를 하면 4가 될 것이라고 test해주는데, 아래 결과를 보면 passed된 것을 확인할 수 있다.

여기서는 2+2가 5가 아니라고 test를 해주는 것이니까 test가 통과되어 passed 되는 것을 확인할 수 있다.

React Testing Library 주요 API

앱을 키고 기본 테스트 진행

폴더를 생성하고, 터미널 창에 npx react-create-app을 해 react app을 생성한 후, npm test를 실행시키면 다음과 같은 창이 나온다.

a를 누르면 다음과 같이 test가 자동으로 진행된다.

q를 누르면 다음과 같이 꺼지는 것을 확인할 수 있다.


App.test.js

기본 테스트가 진행되는 곳이다. 이 파일에서 test case를 작성해놓은 것이다.

<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;

"render" 함수

  • DOM에 컴포넌트를 랜더링하는 함수이다.
  • 인자로 랜더링할 React 컴포넌트가 들어간다.
  • Return은 RTL에서 제공하는 쿼리 함수와 기타 유틸리티 함수를 담고 있는 객체를 리턴한다.(Destructuring 문법으로 원하는 쿼리 함수만 얻어올 수 있다.)

    ====> 소스 코드가 복잡해지면 비추천!! screen 객체를 사용하자. 왜냐하면, 사용해야 할 쿼리가 많아질수록 코드가 복잡해질 수 있기 때문이다.

App.js에 'Learn React'가 있는지 확인하기 위해, App.test.js에 있는 render 함수를 통해 App.js를 먼저 렌더링을 하고, 'Learn React'가 있는지 확인하고, expect와 toBeInTheDocument라는 matcher를 통해 test하여 pass가 뜨는 것이다.

쿼리 함수에 대해서

참고 (공식 문서)

링크텍스트

쿼리 함수란?

쿼리는 페이지에서 요소를 찾기 위해 테스트 라이브러리가 제공하는 방법이다. 여러 유형의 쿼리("get", "find", "query")가 있다. 이들 간의 차이점은 요소가 발견되지 않으면, 쿼리에서 오류가 발생하는지 또는 Promise를 반환하고 다시 시도하는지 여부이다. 선택하는 페이지 콘텐츠에 따라 다른 쿼리가 다소 적절할 수 있다.

get, find, query 의 차이점

쿼리는 페이지에서 요소를 찾기 위해 테스트 라이브러리가 제공하는 방법이다. 여러 유형의 쿼리("get", "find", "query")가 있다. 이들 간의 차이점은 요소가 발견되지 않으면, 쿼리에서 오류가 발생하는지 또는 Promise를 반환하고 다시 시도하는지 여부이다. 선택하는 페이지 콘텐츠에 따라 다른 쿼리가 좀 더 적절할 수 있다.

App.js에서 Learn React를 지우고 각각 실행해보고 결과를 비교해보자.

"getBy..."

쿼리에 대해 일치하는 노드를 반한하고 일치하는 요소가 없거나 둘 이상의 일치가 발견되면 설명 오류를 발생시킨다.
(둘 이상의 요소가 예상되는 경우 getAllBy를 대신 사용.)

"queryBy..."

쿼리에 대해 일치하는 노드를 반환 하고 일치하는 요소가 없으면 null을 반환합니다. 이것은 존재하지 않는 요소를 어설션하는데 유용하다. 둘 이상의 일치 항목이 발견되면 오류가 발생한다(확인된 경우, queryAllBy를 대신 사용).

"findBy..." (getBy + waitFor = findBy)

주어진 쿼리와 일치하는 요소가 발견되면 Promise를 반환한다. 요소가 발견되지 않거나 기본 제한 시간인 1000ms 후에 둘 이상의 요소가 발견되면 약속이 거부된다. 둘 이상의 요소를 찾아야 하는 경우 findAllBy를 사용하자.

"waitFor"

일정 기간 동안 기다려야 할 때, waitFor를 사용해 기대가 통과할 때까지 기다릴 수 있습니다.



Prettier 설치 및 설정

테스팅할 때 matcher를 알맞게 쓰는지 확신이 들지 않을 때가 있으며, 코드의 형식이나 자바스크립트 문법 등을 올바르게 쓰지 못할 때가 있다. 그러한 부분을 도와주는 모듈을 설치해보자.

ESLint

개발자들이 특정한 규칙을 가지고 코드를 깔끔하게 짤수있게 도와주는 라이브러리이다.
자바스크립트를 쓰는 가이드라인을 제시해주고, 문법에 오류가 나면 알려주는 역할 등을 해준다.
ESLint는 포맷터(formatter) 역할도 하지만 주요 기능은 문법 오류를 잡는 것이다.

hello(); // hello 함수를 정의한 것 위에서 hello 함수를 호출해주고 있다. 이것은 문법 오류.

let hello = () => {};

Prettier

주로 코드 형식을 맞추는데 사용한다.
작은따옴표(')를 사용할지 큰 따옴표(")를 사용할지, Indent 값을 2로 줄지 4로 줄지 등, 에러를 찾는 것이 아닌 코드 포맷터 역할이다.

import {useState} from 'react'; //useState를 중괄호 안에 감쌀 때, 공백 없이 감쌀지,

import { useState } from 'react'; //공백을 두고 감쌀지

Prettier는 코드 형식을 맞추는데 사용한다. 테스팅을 위해서 특화된 것은 아니지만 ESLint와 함께 자주 사용한다.

설치한 후, 확정설정에 들어가서 다음 Jsx Single Quote를 체크해주면,

이렇게 Double Quote(큰따옴표)로 되어있는 코드들을

한꺼번에 Single Quote으로 바꿀 수 있다. (shift+option+f)

이외에도 다양한 설정이 가능하다.

ESLint 설치 및 설정하기

ESLint 익스텐션 설치

이미 create-react-app 으로 React를 설치할 때 기본 eslint가 설정되어 있다. 하지만 이 상태로는 VSCode에서 바로 에러를 확인할 수 없고, 앱을 시작했을 때 터미널 상에서 확인할 수 있다.

위와 같이 설치하고 사용함을 해주면,

문제 탭에서 에러를 바로 확인할 수 있다. 에러를 없애주면,

문제가 발견되지 않았음을 바로 확인할 수 있다.

eslint 설정 파일 생성

package.json에 eslintConfig 부분을 지우,고 .eslintrc.json 파일을 생성해준다.
이렇게 하면 PROBELMS(문제) 탭에서 ESLint에서 주는 기본적인 경고들을 확인 할 수 있다.

이 부분을 복사하고, package.json에서는 지워주고, 다음과 같이 .eslintrc.json에 옮겨준다.

{
    "extends": [
        "react-app",
        "react-app/jest"
    ]
}

ESLint Testing Plugins 설치

이제는 Testing을 도와주는 ESlint를 설치해보자.

Plugins 란 ?

eslint에서 기본으로 제공하지 않는 다양한 규칙을 플러그인을 통해 사용할 수 있다.
예를 들어, react에 관련된 린트설정을 위해서는 eslin-plugin-react를 사용하면 되고, react hooks에 관련된 규칙을 적용시켜주려면 eslint-plugin-react-hooks를 사용하면 된다.

npm install 
eslint-plugin-testing-library //testing-library : render로 Dom 그리는 부분
eslint-plugin-jest-dom // jest-dom : expect-matcher로 테스트

내부 설정

plugins 항목

플러그인 추가 추가할 때, eslint-plugin- 부분은 생략이 가능하다.

extends 항목

플러그인을 추가 한 후에 규칙을 정해줘야 사용가능하다. 그래서 extends 항목에 사용하고자 하는 규칙을 설정한다.
vue, angular, react 중에 react를 위한 규칙 recommended는 추천이 되는 걸 사용하는 것이다.

<.eslintrc.json>

{
    "plugins": [
        "testing-library",
        "jest-dom"
    ],

    "extends": [
        "react-app",
        "react-app/jest",
        "plugin:testing-library/react",
        "plugin:jest-dom/recommended"
    ]
}

lint가 잘 작동하는지 확인

App.test.js에 다음 코드를 추가해서 확인하자.

const lintTest = screen.getAllByRole("button", {
    name: "lintTest",
  });
  
  expect(lintTest.textContent).toBe("lintTest");

그러면 다음과 같이 에러표시줄이 뜬다.

사실 작성한 코드도 맞는건데, 마우스 커서를 올리면,

eslint가 더 나은 방법을 알려준다 이를 빠른 수정을 클릭해주고 fix를 해주면,

다음과 같이 더 나은 코드로 변환시켜준다.

이로써 lint가 잘 작동하는 것을 확인했다.

profile
다양한 활동을 통해 인사이트를 얻는 것을 즐깁니다. 저 또한 인사이트를 주는 사람이 되고자 합니다.

0개의 댓글

관련 채용 정보