Test Driven Development

미루고 미루던 테스트 케이스


1. TDD 방법론

코드를 작성하기 전 테스트를 쓰는 소프트웨어 개발 방법론이다. 작은 단위의 테스트 케이스를 작성하고, 이를 통과하는 코드를 작성하는 과정을 반복하는 것을 말한다.

… -> Write Failing Test -> Make Test Pass -> Refactor -> …

  • Write Failing Test: 실패하는 테스트 코드를 먼저 작성한다.
  • Make Test Pass: 테스트 코드를 성공시키기 위한 실제 코드를 작성한다.
  • Refactor: 중복 코드 제거, 일반화 등의 리팩토링을 수행한다.

1.1. 이유

예상하지 못했던 버그를 줄여 소요 시간을 줄일 수 있기 때문이다.

1.2. 방법

describe, it, assert, expect, 등 js내장기능이 아니라 테스트 프레임워크에서 제공하는 테스트 작성을 위한 도구이다.

2. React 환경에서 테스트하기

Testing Library, Jest를 이용한다.

2.1. 테스트 환경 확인

2.1.1. 생성

npx create-react-app test-practice

테스트환경이 create-react-app에 내장되어있다.

// package.json
...
"dependencies": {
  // jest-dom 제공하는 custom matcher를 사용할  있다.
  "@testing-library/jest-dom": "^x.xx.x",
  // react 컴포넌트 요소를 찾기 위한 query가 포함된다.
  "@testing-library/react": "^xx.x.x",
  // click등 사용자 이벤트에 이용
  "@testing-library/user-event": "^xx.x.x",
  ...
},
...

2.1.2. 확인

src폴더 내 setupTests.js, App.test.js라는 파일에 기 테스트가 있다.

npm run test
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();
});
  1. 테스트하는 컴포넌트를 render()함수로 전달한다. react-testing-library에서 테스트를 진행할 컴포넌트를 render()함수의 인자로 전달한다.
  2. screen의 다양한 메서드 중 getByText()메서드를 이용해 render()에서 가져온 App컴포넌트 중 “learn react”라는 문자열이 있는지 확인하여 linkElement에 할당하고 있다. (“i”는 Regular Expression으로 “i”를 붙임으로써 대소문자를 구분하지 않게 한다.)
  3. expect함수의 인자로 지정한 요소가 document.body에 존재하는지 toBeInTheDocument함수를 사용하여 체크하고 있다. 여기서 ToBeInTheDocument함수는 matchers함수라 부른다.
// pass
test('2+2=4', () => {
  expect(2+2).toBe(4);
});

// fail
test('2+2=4', () => {
  expect(2+2).toBe(5);
});
PASS src/App.test.js
FAIL src/Example.test.js
- 2+2=4
  expect(received).toBe(expected)

  Expected: 5
  Received: 4

  1 | test('2+2=4', () => {
  2 |   expect(2+2).toBe(5);
                    ^  
  3 | });
  4 |

  at Object.<anonymous> (src/Example.test.js:2:17)

Test Suites:  1 failed, 1 passed, 2 total
Tests:        1 failed, 1 passed, 2 total
Snapshots:    0 total
Time:       .....
Ran all test suites.

Watch Usage: Press w to show more.
// test와 동일
it('2+2=4', () => {
  expect(2+2).toBe(4);
});

// 파일하나의 여러개를 포함
describe('여러개들', () => {
  test('1+1=2', () => {
    expect(1+1).toBe(3);
  });
  test('2+1=3', () => {
    expect(2+1).toBe(3);
  })
})

참조

github: testing-library/jest-dom
jest: main
mocha: main
chai: main