리액트 테스팅(1)
jest와 react-testing-library
2022-12-10
* Jest - Facebook에서 만든 테스팅 프레임 워크.
주로 단위 (unit) 테스트를 위해 사용.
-
filename.test.js
-
filename.spec.js
All files inside "tests" folders
-
describe -> 테스트를 그룹화 하는데 사용
-
test(it) - 개별 테스트를 수행
-
test(it) - 개별 테스트를 수행
-
test(it) - 개별 테스트를 수행
-
expect 함수는 값을 테스트할 때마다 사용, matcher(다른 방법으로 값을 테스트)와 함께 사용
시작해보기
cra 폴더로 가서
npm test
파일명에 test가 들어간 파일을 찾는다.
a로 App.test.js에 있는 모든 테스트를 실행
test('renders learn react link', () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});
- render함수는 DOM에 컴포넌트를 랜더링 하는 함수, return은 RTL(리액트 테스트 라이브러리)에 쿼리 함수와 기타 유틸리티를 담고 있는 객체를 리턴한다.
test('renders learn react link', () => {
const { getByText } = render(<App />);
const linkElement = getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});
아래 처럼도 쓸수 있다. (쿼리함수를 직접 쓰는 경우는 거의 없고 screen 객체로 이용)
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
linkElement가 Document안에 있는지 판단하는 matcher
쿼리함수
쿼리는 페이지에서 요소를 찾기 위해 테스트 라이브러리가 제공하는 방법
-
getBy~: 쿼리에 대해 일치하는 노드를 반환, 일치하는 요소가 없거나 둘 이상의 일치가 발견되면 에러를 반환(둘 이상의 요소는 getAllBy~ 사용)
-
queryBy~: 쿼리에 대해 일치하는 노드 반환, 일치하는 요소가 없으면 null을 반환
-
findBy~: (getBy + waitFor)주어진 쿼리와 일치하는 요소가 발견되면 Promise를 반환 (둘 이상의 요소는 findAllBy~ 사용)
-
waitFor: 일정 기간 동안 기다리도록
린트
"eslint-plugin-jest-dom"
"eslint-plugin-testing-library"
TDD(Test Driven Development)
실제 코드를 작성하기 전에 테스트 코드를 먼저 작성
간단한 카운팅 앱 만들어보기
test('Counter starts at 0', () => {
render(<App />);
// screen object로 원하는 엘리멘트에 접근(ID)
const counterElement = screen.getByTestId('counter');
// id가 counter인 엘리멘트의 텍스트가 0인가?
expect(counterElement).toHaveTextContent(0);
});
import './App.css';
import {useState} from 'react';
function App() {
const [count, setCount] = useState(0);
return (
<div className="App">
<header className="App-header">
<h3 data-testid="counter">{count}</h3>
</header>
</div>
);
}
export default App;
- 버튼 추가하기
test('Minus Button', () => {
render(<App />);
const buttonElement = screen.getByTestId('minus-button');
expect(buttonElement).toHaveTextContent('-');
});
test('Plus Button', () => {
render(<App />);
const buttonElement = screen.getByTestId('plus-button');
expect(buttonElement).toHaveTextContent('+');
});
<div>
<button data-testid="minus-button">-</button>
<button data-testid="plus-button">+</button>
</div>
FireEvent API
유저가 발생시키는 액션(이벤트)에 대한 테스트
- 버튼 이벤트 추가하기
test('When the + button is pressed, the counter change to 1', () => {
render(<App />);
const buttonElement = screen.getByTestId('plus-button');
// 버튼 클릭
fireEvent.click(buttonElement);
// plus 버튼 클릭시 counter 엘리먼트는 1
const counterElement = screen.getByTestId('counter');
expect(counterElement).toHaveTextContent(1);
});
test('When the - button is pressed, the counter change to -1', () => {
render(<App />);
const buttonElement = screen.getByTestId('minus-button');
// 버튼 클릭
fireEvent.click(buttonElement);
// minus 버튼 클릭시 counter 엘리먼트는 -1
const counterElement = screen.getByTestId('counter');
expect(counterElement).toHaveTextContent(-1);
});
const [count, setCount] = useState(0);
const handlePlus = () => {
setCount((prevState) => prevState + 1);
};
const handleMinus = () => {
setCount((prevState) => prevState - 1);
};
return (
<div className="App">
<header className="App-header">
<h3 data-testid="counter">{count}</h3>
<div>
<button data-testid="minus-button" onClick={handleMinus}>
-
</button>
<button data-testid="plus-button" onClick={handlePlus}>
+
</button>
</div>
</header>
</div>
);
- on/off 버튼 색상과 클릭시 -, +버튼 disabled
test('on/off button has blue color', () => {
render(<App />);
const buttonElement = screen.getByTestId('on/off-button');
expect(buttonElement).toHaveStyle({backgroundColor: 'blue'});
});
test('Prevent -,+ button from being pressed when the on/off button is clicked', () => {
render(<App />);
const onOffButtonElement = screen.getByTestId('on/off-button');
fireEvent.click(onOffButtonElement);
const plusButtonElement = screen.getByTestId('plus-button');
const minusButtonElement = screen.getByTestId('minus-button');
expect(plusButtonElement).toBeDisabled();
expect(minusButtonElement).toBeDisabled();
});
<button data-testid="on/off-button" style={{backgroundColor: 'blue'}} onClick={handleDisabled}>
on/off
</button>