이번 블로깅은 소프트웨어를 검증하는 방법론 중 하나인 TDD, 테스트 주도 개발론에 대한 글이다.
TDD(Test-driven Development)는 코드를 작성하기 전에 테스트를 쓰는 소프트웨어 개발 방법론이다. TDD를 통해 소프트웨어를 개발한다는 것은 작은 단위의 테스트 케이스를 작성하고, 이를 통과하는 코드를 작성하는 과정을 반복하는 것을 의미한다.
TDD는 아래 3가지의 단계를 반복하여 진행한다.
테스트 코드를 작성해야 하기 때문에 시간이 오래 걸리는 것처럼 느껴지지만, 오히려 예상하지 못했던 버그를 줄여 소요 시간을 줄일 수 있다. 개발 과정에서 코드는 다양한 조건에 의해 계속해서 삽입, 수정, 삭제된다. 이 과정에서 코드가 중복되거나 불필요한 코드가 남게 된다. 이로 인해 여러 가지 버그가 발생하거나, 디버깅 또한 어려워지는 현상이 발생하기도 한다. 결국 그런 코드를 유지보수하기 위해서는 처음 개발할 때 아꼈던 리소스보다 더 많은 리소스를 투입해야 하는 경우가 발생합니다. TDD는 이러한 상황을 방지 할 수 있다.
React에서 테스트는 Testing Library, Jest를 이용해서 할 수 있다.
Testing Libarary에서 React용 React Testing Library을 제공하고 있다. create-react-app을 이용하여 React 프로젝트를 생성하면 자동으로 Testing Libarary를 이용할 수 있다. 테스트를 실행하고 싶은 컴포넌트나 클릭 이벤트등 다양한 곳에 쓸 수 있다.
Jest는 JavaScript의 Testing Framework / Test Runner로써, 테스트 파일을 자동으로 찾아 테스트를 실행하고, 테스트를 실행한 결과 기대만큼 올바른 값을 가지고 있는지 함수를 이용하여 체크하여 테스트가 성공인지 실패인지를 판단해 준다.
Testing Libarary와 Jest는 역할이 각각 다르기 때문에 React에 대한 테스트를 진행할 때는 어느 한쪽 라이브러리를 이용하는 것만으로는 테스트를 할 수 없다.
npx create-react-app 명령을 실행하여 React 프로젝트를 만들어 보자. create-react-app에서 React 프로젝트를 생성하면 테스트 환경이 설정되어 있기 때문에 바로 테스트가 가능하다.
npx create-react-app
으로 새로운 프로젝트를 생성한다.
프로젝트 생성 후, package.json 파일을 확인해보면 dependencies 안에 @testing이라는 접두어가 붙은 3개의 라이브러리를 확인할 수 있다. 이것들이 바로 테스트를 수행할 때 이용하는 라이브러리다.
// package.json
{
...
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
...
}
src 폴더 안을 확인해 보면, setupTests.js 와 App.test.js 라는 이름의 파일을 확인할 수 있다. App.test.js 파일에는 간단한 테스트가 이미 만들어져 있다.
// setupTests.js
import '@testing-library/jest-dom';
test 함수는 Jest 함수로 테스트를 실행할 때 반드시 이용하는 함수다. test 함수의 첫 번째 인자는 테스트가 어떤 내용인지 나중에 다시 읽어도 테스트 내용을 알 수 있는 설명을 작성한다. 두 번째 인자는 하고자 하는 테스트를 함수의 형태로 넣는다.
두 번째 인자로 들어간 함수를 자세히 살펴보자.
첫번째 줄을 보면, 테스트하고자 하는 컴포넌트를 render()함수로 전달하고 있다. react-testing-library에서는 테스트를 진행할 컴포넌트를 render()함수의 인자로 전달한다.
두번째 줄에 있는 screen의 다양한 메소드 중 getByText() 메서드를 이용하여 render()에서 가져온 App 컴포넌트 중 "learn react"라는 문자열이 있는지 확인하여 linkElement에 할당하고 있다. “i”는 Regular Expression으로 대소문자를 구분하지 않게 만들어 준다.
세번째 줄에서는 expect 함수의 인자로 지정한 요소가 document.body에 존재하는지 toBeInTheDocument 함수를 사용하여 체크하고 있다. 여기서 toBeInTheDocument 함수는 matchers 함수라고 부른다.
// App.test.js
import { render, screen } from '@testing-library/react';
import App from './App';
test('renders learn react link', () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});
npm run test 명령어로 test를 실행시킬 수 있다.
No tests found related to files changed since last commit.
Press `a` to run all tests, or run Jest with `--watchAll`.
Watch Usage
› Press a to run all tests.
› Press f to run only failed tests.
› Press q to quit watch mode.
› Press p to filter by a filename regex pattern.
› Press t to filter by a test name regex pattern.
› Press Enter to trigger a test run.
테스트를 실행하면 위와 같은 대화식 메시지가 나타난다. 메시지를 보면 키보드 키에 따라 다양한 처리를 할 수 있다는 것을 알 수 있다.
a키를 누르면 테스트가 실행되고, 실행한 테스트에 성공했음을 의미하는 PASS 메시지를 확인할 수 있다.
PASS src/App.test.js
✓ renders learn react link (48 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 2.635 s
Ran all test suites.
Watch Usage: Press w to show more.
코드 테스트를 위한 코드를 또 작성해야 된다니.... 코딩의 세계는 연약한 아기개발자들에게 너무 가혹하다ㅜㅜ 멋진 개발자가 되기 위해 오늘도 꾹참고 달려간다! 오늘도 내일도 화이팅이다!