티스토리 뷰

TDD 원칙대로 세팅

TDD 원칙대로라면 기능 코드를 추가하기 전에 테스트를 작성해야 합니다. 

 

이번 예제에서는 App.js에서 할 거라 App.js를 비워주겠습니다.

 

📜 App.js 파일

function App() {
  return <div />;
}

export default App;

 

1. 테스트하려는 내용들 세팅

전역 테스트 메서드인 test에는 총 2개의 인자가 들어간다고 했었습니다. 첫 번째 인자에는 테스트의 문자열 설명, 두 번째 인자에는 테스트 함수입니다. 우선 내가 테스트하고자 하는 내용들을 모두 적어서 세팅해봅시다.

저는 버튼에 올바르게 초기 색상이 적용되었는지, 클릭 시 파란색으로 바뀌는지 기능 테스트까지 해보려고 합니다.

 

📜 App.test.js 파일

test('button has correct initial color', () => {});

test('button turns blue when clicked', () => {});

테스트할 대상은 모두 적어주었고, 이제 테스트 방식에 해당하는 두 번째 인자로 테스트 함수를 작성해 봅시다.

 

2. 테스트 함수 작성

(1) 렌더링할 대상을 render 함수 안에 적는다.

render(<App />);

(2) 살펴보려는 요소를 찾는다.

여기에서는 렌더링을 통해 생성된 가상 DOM에 엑세스할 수 있는 전역 객체 screen을 사용합니다. 각 요소들은 역할을 가지고 있는데, 이때 역할은 아래 사이트에서 살펴볼 수 있습니다.

 

Accessible Rich Internet Applications (WAI-ARIA) 1.1

A section of a page that consists of a composition that forms an independent part of a document, page, or site. An article is not a navigational landmark, but may be nested to form a discussion where assistive technologies could pay attention to article ne

www.w3.org

render(<App />);
const colorButton = screen.getByRole('button', { name: 'Change to blue' });

위 코드에서 name표시되는 텍스트를 의미합니다.

(3) Matcher를 통해 테스트할 내용을 작성한다.

이제 버튼의 색상도 테스트해야 하는데, 이를 위해 jest-dom에 있는 다른 옵션을 살펴보겠습니다.

아래는 Github의 jest-dom 페이지입니다. 여기에서 커스텀 matcher들이 무엇이 있는지를 확인할 수 있습니다.

 

GitHub - testing-library/jest-dom: Custom jest matchers to test the state of the DOM

:owl: Custom jest matchers to test the state of the DOM - GitHub - testing-library/jest-dom: Custom jest matchers to test the state of the DOM

github.com

이 중에서도 toHaveStyle을 사용해 버튼의 배경색이 무엇인지 확인하려고 합니다.

render(<App />);
const colorButton = screen.getByRole('button', { name: 'Change to blue' });
expect(colorButton).toHaveStyle({ backgroundColor: 'red' });

여기까지하면 테스트 하나 작성을 완료한 것입니다.

3. 테스트 진행 상황 확인 → 레드 부분 🔴

npm test를 입력하여 확인해봅시다. 우리는 테스트 코드만 작성하고 실제 컴포넌트는 구현하지 않았으니 당연히 실패가 뜨는 것이 당연하다고 생각하고 실행해봅시다.

예상대로 테스트 결과가 나왔습니다. 여기까지 레드-그린 테스트에서 레드 부분은 성공적으로 마친 것입니다 :)

 

4. 실제 구현 하기 → 그린 부분 🟢

App.js 파일로 가서 테스트가 성공할 수 있도록 실제 구현을 하기 고쳐봅시다.

 

📜 App.js 파일

function App() {
  return (
    <div>
      <button style={{ backgroundColor: 'red' }}>Change to blue</button>
    </div>
  );
}

export default App;

다시 테스트를 진행해보니 테스트에 성공한 것을 확인할 수 있었습니다.

 


➕ Roles 디버깅을 위한 logRoles

위 예시 코드에서 내가 작업하는 버튼의 역할이 있는 걸 몰랐다고 한다면 이 경우 사용할 수 있는 디버깅 도구가 있습니다.

아래 사이트를 통해 logRoles 메서드에 관한 내용을 확인할 수 있습니다.

 

Accessibility | Testing Library

Testing for Accessibility

testing-library.com

  

📜 App.test.js 파일

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

test('button has correct initial color', () => {
  const { container } = render(<App />);
  logRoles(container);

  const colorButton = screen.getByRole('button', { name: 'Change to blue' });
  expect(colorButton).toHaveStyle({ backgroundColor: 'red' });
});

위와 같이 작성하고 실행하면 logRoles의 출력값을 볼 수 있습니다.

내용을 보게 되면, 해당 컴포넌트에 있는 역할이 출력되고 그 이름을 알 수 있습니다.

 


아까 우리가 테스트할 내용을 2개 작성해 두었는데 나머지 하나가 버튼을 클릭했을 때 파란색으로 바뀌는지였습니다. 이 부분에 대해서도 순서에 맞게 작성해보겠습니다.

이번에는 테스트할 때 '버튼이 클릭되는 것'을 테스트해야 하니까 버튼을 클릭을 해야하는데 이때 fireEvent 라는 객체를 통해 이루어지도록 할 것입니다. 또한 버튼이 눌린 후 텍스트가 Change to red로 바뀐 경우도 expect할 것입니다 :)

 

📜 App.test.js 파일

test('button turns blue when clicked', () => {
  render(<App />);
  const colorButton = screen.getByRole('button', { name: 'Change to blue' });

  // 버튼을 클릭
  fireEvent.click(colorButton);

  // 배경 색이 파란색으로 바뀌는 것을 expect
  expect(colorButton).toHaveStyle({ backgroundColor: 'blue' });

  // 눌렸으므로 버튼 텍스트도 Change to red가 되는 것을 expect
  expect(colorButton).toHaveTextContent('Change to red');
});

위 코드를 작성하고 테스팅을 시작하면 아직 구현을 안 해놓았으니 당연히 실패가 뜰 것입니다. 레드 과정이죠 ! 🔴

아직 구현을 하지 않아서 발생하는 당연한 문제입니다.

 

이제 구현을 해봅시다! 그린 과정입니다 🟢

 

📜 App.js 파일

import { useState } from 'react';

function App() {
  const [color, setColor] = useState('red');

  const onClickRedBtn = () => {
    setColor('blue');
  };

  return (
    <div>
      <button style={{ backgroundColor: color }} onClick={onClickRedBtn}>
        Change to {color === 'red' ? 'blue' : 'blue'}
      </button>
    </div>
  );
}

export default App;

우리가 구현하고 싶었던 부분을 기능으로 구현해보았습니다. 그리고 테스트 한 결과는 다음과 같았습니다.

 

728x90
LIST
250x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함