리액트에서는 Testing Library, Jest를 통해 테스트 가능
- 두 개의 역할이 각각 다르므로 함께 사용해야 함
- Vue, Svelte에서도 사용 가능
create-react-app
으로 설치하면 자동으로 해당 라이브러리가 같이 설치된다
: JavaScript의 Testing Framework / Test Runner
npx create-react-app 생성폴더명
"dependencies": {
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.3.0",
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
@testing-library/jest-dom
: Jest-dom 제공하는 custom matcher를 사용할 수 있게 해줌@testing-library/react
: 컴포넌트의 요소를 찾기 위한 query가 포함됨@testing-library/user-event
: click 등 사용자 이벤트에 이용함npm run test
이나 npm t
)해보면test
함수test
함수react-testing-library
를 통해 render()
함수의 인자로 테스트할 컴포넌트를 전달getByText()
메서드로 render(<App />);
로 가져온 App컴포넌트에 learn react
라는 문자열이 있는지 확인하고 linkElement
변수에 할당.i
: Regular Expression으로 "i"를 붙임으로써 대소문자 구분안함)document.body
에 존재하는지 toBeInTheDocument
함수를 사용하여 체크.toBeInTheDocument
함수는 matchers
함수라고 부름.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();
});
App.test.js 파일에서 test
, expect
함수는 Jest의 함수고, toBeInTheDocument
는 jest-dom 라이브러리에 포함된 Custom matchers다.
Q, 하지만 아직 jest-dom을 import 한 적이 없는데?
A, jest-dom은 src/setupTests.js 파일 내에서 import했기 때문이다.
만약 setupTests.js에서 import 삭제하면 toBeInTheDocument 함수를 사용할 수 없다.
src/파일명.test.js
or src/파일명.spec.js
생성toBe
함수 : matchers 함수 중 하나로 expect
함수에 지정한 값이 toBe
함수에 지정한 값과 일치하는지 체크. npm run test
하고 a
를 선택하면 Example.test.js와 App.test.js가 모두 실행되고 PASS 출력// src/Example.test.js
test("1 더하기 1은 2", () => {
expect(1 + 1).toBe(2);
});
it
함수로도 동일한 결과 출력// src/Example.test.js
it("1 더하기 1은 2", () => {
expect(1 + 1).toBe(2);
});
describe
함수 : 하나의 파일에 it
, test
함수 여러개 포함가능// src/Example.test.js
describe("간단한 테스트", () => {
test("1 더하기 1은 2", () => {
expect(1 + 1).toBe(2);
});
it("2 더하기 2은 4", () => {
expect(2 + 2).toBe(4);
});
});
describe
함수 블록 - Test Suites라고 부름test/it
함수 블록 - Test(Test Case)라고 부름// Light.jsx
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;
npm start
해보기import "./App.css";
import Light from "./components/Light";
function App() {
return <Light name="스위치" />;
}
export default App;
// 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();
})
// Light.test.js
import { fireEvent, render, screen } from "@testing-library/react";
import Light from "./Light";
describe("컴포넌트 테스트", () => {
it("renders Light Component", () => {
render(<Light name="전원" />);
const nameElement = screen.getByText(/전원 off/i);
expect(nameElement).toBeInTheDocument();
});
it("off button disabled", () => {
render(<Light name="전원" />);
const offButtonElement = screen.getByRole("button", { name: "OFF" });
expect(offButtonElement).toBeDisabled();
});
it("on button enable", () => {
render(<Light name="전원" />);
const onButtonElement = screen.getByRole("button", { name: "ON" });
expect(onButtonElement).not.toBeDisabled();
});
it("change from off to on", () => {
render(<Light name="전원" />);
const onButtonElement = screen.getByRole("button", { name: "ON" });
fireEvent.click(onButtonElement);
expect(onButtonElement).toBeDisabled();
});
});
getByText
props로 전달된 전원이 올바르게 표시되어 있는지 확인
getByRole
button을 지정하고, 버튼이 2개이므로 옵션의 name을 이용하여 OFF 버튼을 찾음. toBeDisabled
로 OFF버튼이 disabled 상태인지 확인
expect(onButtonElement).not.toBeDisabled()
toBedisabled
함수 앞에 not
을 붙여 ON 버튼이 disabled 안된 것을 테스트
fireEvent
버튼 click 등 이벤트 유무 테스트
click
메서드에 전달인자로 테스트할 요소 전달