React와 TDD

leekoby·2023년 3월 29일
0

React

목록 보기
9/10
post-thumbnail

🔧변경내용🔨

제목날짜내용
발행일23.03.29

📌들어가기에 앞서

해당 포스트는 React의 TDD에 대해 학습한 내용을 정리하며 기록한 것입니다.




React 환경에서 테스트하기

React에서 테스트는 Testing Library, Jest를 이용해서 할 수 있다.

  • React에서만 쓸 수 있는 라이브러리는 아님
  • Vue, Svelte 등 다른 프레임워크에서도 사용가능

Testing Libarary

  • React용 React Testing Library을 제공
  • create-react-app으로 React 프로젝트를 생성하면 자동으로 Testing Libarary를 사용가능
  • 테스트를 실행하고 싶은 컴포넌트나 클릭 이벤트등 다양한 곳에 쓸 수 있다.

Jest는 JavaScript의 Testing Framework / Test Runner

  • 테스트 파일을 자동으로 찾아 테스트를 실행
  • 테스트를 실행한 결과 기대만큼 올바른 값을 가지고 있는지 함수를 이용하여 체크
  • 테스트가 성공인지 실패인지를 판단

Testing Libarary와 Jest는 역할이 각각 다르기 때문에 React에 대한 테스트를 진행할 때는 어느 한쪽 라이브러리를 이용하는 것만으로는 테스트를 할 수 없다.




📖 1. React 기본 테스트 환경 확인하기


1-1. 새로운 React 프로젝트 생성하기

npx create-react-app

명령을 실행하여 React 프로젝트를 만들어 보자.

create-react-app에서 React 프로젝트를 생성하면 테스트 환경이 설정되어 있기 때문에 바로 테스트가 가능하다.

프로젝트 생성 후 package.json 파일을 확인하면 dependencies 안에 @testing이라는 접두어가 붙은 3개의 라이브러리를 확인할 수 있다.

이게 바로 테스트를 수행할 때 이용하는 라이브러리다.

scripts안에 test가 있는 것으로 미루어 볼 때, 테스트를 실행할 때는 npm run test를 이용하면 된다는 것을 알 수 있다.

@testing-library/jest-dom :

  • jest-dom에서 제공하는 custom matcher를 사용할 수 있게 해준다.

@testing-library/react :

  • 컴포넌트의 요소를 찾기 위한 query가 포함

@testing-library/user-event :

  • click 등 사용자 이벤트에 사용


1-2. 테스트 파일 확인하기

src 폴더 안을 확인해 보면, setupTests.js 와 App.test.js 라는 이름의 파일을 확인할 수 있다.

App.test.js 파일에는 간단한 테스트가 이미 만들어져 있다.

package.json 파일과 파일의 구성을 보면 npx create-react-app 명령을 실행하여 프로젝트를 생성해서 테스트를 하기 위한 환경이 미리 설치 되어 있는 것을 알 수 있다.

npm run test 명령어로 test를 실행시킬 수 있다.

테스트를 실행하면 위와 같은 대화식 메시지가 나타난다.

메시지를 보면 키보드 키에 따라 다양한 처리를 할 수 있다는 것을 알 수 있다.

지금은 Press a to run all tests. 라고 설명되어 있는 부분을 실행하기 위해 a키를 눌러 보자.

a키를 누르면 테스트가 실행되고, 실행한 테스트에 성공했음을 의미하는 PASS 메시지를 확인할 수 있다.

이외에도 테스트 건수나 테스트에 걸린 시간 등도 확인이 가능하다.


App.test.js로 가서 어떤 코드가 작성되어 있는지 살펴보자.

test 함수는 Jest 함수로 테스트를 실행할 때 반드시 이용하는 함수다.

test 함수의 첫 번째 인자는 테스트가 어떤 내용인지 나중에 다시 읽어도 테스트 내용을 알 수 있는 설명을 작성한다.

두 번째 인자는 하고자 하는 테스트를 함수의 형태로 넣는다.

두 번째 인자로 들어간 함수를 자세히 살펴보자.

  1. 함수 내부의 첫번째 줄에서, 테스트하고자 하는 컴포넌트를 render()함수로 전달하고 있다.
    react-testing-library에서는 테스트를 진행할 컴포넌트를 render()함수의 인자로 전달한다.
  1. 두번째 줄에 있는 screengetByText() 메서드를 사용해서 render()에서 가져온 App 컴포넌트 중 "learn react"라는 문자열이 있는지 확인하여 linkElement에 할당하고 있다.

    • “i”는 Regular Expression으로 "i"를 붙임으로써 대소문자를 구분하지 않게 만든다.
  2. 세번째 줄에서는 expect 함수의 인자로 지정한 요소가 존재하는지 toBeInTheDocument 함수를 사용하여 체크하고 있다.

    • 여기서 toBeInTheDocument 함수는 matchers 함수라고 부른다.

App.test.js 파일 중 test 함수, expect 함수는 Jest의 함수고,
toBeInTheDocument는 jest-dom 라이브러리에 포함된 Custom matchers다.

하지만 jest-dom을 import 한 적이 없다. 어디에 있을까

jest-dom은 src 폴더의 setupTests.js 파일 내에서 import 되고 있다.

setupTests.js 파일에서 import를 삭제하면 toBeInTheDocument 함수를 사용할 수 없게 된다.


npm run test 를 실행시켰을 때의 결과는 PASS였다.

테스트로 확인한 부분 App.js 파일을 보면 <a>태그의 콘텐츠로 "Learn React"를 찾을 수 있다.

App.test.js의 내부에서 screen의 getByText 메서드로 찾아낸 부분이 바로 이 부분이다.

그런데 만약, Learn의 첫 글자인 L을 지운 다음 테스트를 실행하면 어떻게 될까?

learn react를 가진 요소를 찾지 못해 위와 같이 FAIL이 뜨고 테스트가 실패하게 된다.


1-3. 간단한 테스트 직접 만들기

테스트를 좀 더 이해하기 위해 Jest만을 이용하여 테스트를 실행하고 테스트의 기본적인 규칙이나 기술방법을 확인해보자.

src폴더에 Example.test.js 파일을 생성했다.

테스트를 실행하기 위해서는 파일명을 <파일명>.test.js처럼 하면 된다.
(<파일명>.spec.js에서도 가능합니다.)

파일명을 이렇게 짓고 테스트를 작성하면, Jest가 테스트 파일로 판단하여 작동한다.

Jest만을 이용하므로 React의 컴포넌트를 이용하지 않고 덧셈의 간단한 테스트를 만들어보자.

테스트는 test 함수 안에 쓰고 test 함수의 첫 번째 인자에는 테스트에 대한 설명을, 두 번째 인자에는 테스트의 내용을 함수의 형태로 작성한다.

expect 함수의 인자로 2+2를 넣고 toBe함수에 4라는 결과를 지정하여 테스트를 해보자.

toBe 함수는 matchers 함수 중 하나로 expect 함수에 지정한 값이 toBe 함수에 지정한 값과 일치하는지 체크한다.

npm run test를 실행하여 "a"를 선택하면 Example.test.js와 App.test.js가 모두 실행이 된다.

2+2의 결과로 4를 지정하였으니 PASS의 결과 나온다.

그렇다면 만약 toBe 함수의 인자를 5로 바꾸면 어떻게 될까?

이번에는 Example.test.js에서 FAIL이 발생했다.

메시지를 잘 읽어보면, 왜 테스트가 실패했는지 확인할 수 있다.

test 함수 대신 it 함수를 사용해도 같은 결과가 나온다.

describe함수를 사용하면 it함수나 test함수를 하나의 파일에 여러 개 포함할 수 있다.

describe 함수 블록은 Test Suites라고 불리며 test/it 함수 블록은 Test(Test Case)라고 한다.



📖 2. 직접 만든 컴포넌트 테스트하기


2-1. 컴포넌트 만들기

Jest의 간단한 기능을 알아봤으니 이제 본격적으로 React의 컴포넌트를 이용하여 테스트 연습을 해보자.

src 폴더에 components 폴더를 생성하고 Light.jsx 파일을 작성한 후, App.test.js 파일은 삭제하자.

import {useState} from 'react';

function Light({ name }) {
	const [light, setLight] = useState(false);

	return (
		<div>
			<h1>
				{name} {light ? 'ON' : 'OFF'}{' '}
			</h1>
			<button
				onClick={() => setLight(true)}
				disabled={light ? true : false}
			>
				ON
			</button>
			<button
				onClick={() => setLight(false)}
				disabled={!light ? true : false}
			>
				OFF
			</button>
		</div>
	);
}

export default Light;

Light.js는 전원의 상태를 OFF에서 ON으로 전환하는 심플한 컴포넌트다.

name은 props로 전달받아 <h1>태그를 사용하여 표시합니다.

App.js 파일에서 Light.jsx 파일을 import하고 있다.

npm start 명령을 입력하여 실행해 보자.


2-2. 컴포넌트 테스트하기

이렇게 만든 컴포넌트를 테스트 해보자.

먼저 compoents 폴더 아래에 Light.test.js 파일을 만들고 아래와 같이 작성해보자.

import { render, screen } from '@testing-library/react';
import Light from './Light';

it('renders Light Component', () => {
	render(<Light name="전원" />);
	const nameElement = screen.getByText(/전원 off/i);
	expect(nameElement).toBeInTheDocument();
})

getByText를 이용하여 props로 전달된 전원이 올바르게 표시되어 있는지 확인해 보자.

올바르게 코드를 작성했다면 PASS가 나온다.

이번에는 OFF 버튼이 disabled로 되어 있는지 matchers 함수의 toBeDisabled 함수를 이용해 테스트를 작성해보자.

getByRole을 이용하여 button을 지정했고, 버튼이 2개이므로 옵션의 name을 이용하여 OFF 버튼을 찾는다.

현재 OFF버튼이 disabled 상태이기 때문에, 테스트의 결과도 PASS로 나오는 것을 확인할 수 있다.

it('off button disabled', () => {
	render(<Light name="전원" />);
	const offButtonElement = screen.getByRole('button', { name: 'OFF' });
	expect(offButtonElement).toBeDisabled();
})

반대로 ON 버튼이 disabled가 아니라는 것을 테스트하려면 어떻게 할 수 있을까? toBedisabled 함수 앞에 not을 붙이면 구현할 수 있다.

it('on button enable', () => {
  render(<Light name="전원" />);
  const onButtonElement = screen.getByRole('button', { name: 'ON' });
  expect(onButtonElement).not.toBeDisabled();
});

버튼 클릭 이벤트의 유무도 테스트할 수 있습니다. 그럴 때는 fireEvent를 사용한다.

fireEvent를 import하고, fireEventclick메서드에 전달인자로 테스트하고자 하는 요소를 전달한다.

import { fireEvent, render, screen } from '@testing-library/react';
import Light from './Light';

it('change from off to on', () => {
	render(<Light name="전원" />);
	const onButtonElement = screen.getByRole('button', { name: 'ON' });
	fireEvent.click(onButtonElement);
	expect(onButtonElement).toBeDisabled();
})

여기까지 React 환경에서 Jest를 이용하여 테스트를 만들고 실행하는 튜토리얼을 진행해 보았다.




📚 레퍼런스

Jest · Delightful JavaScript Testing

React Testing Library

0개의 댓글