๐ React Compontets testing
๋ฆฌ์กํธ ๊ณต์ํ์ด์ง๋ฅผ ๋ณด๋ฉด components testing์ ์๋์ ๊ฐ์ด ๋๊ฐ์ง ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ถ์ฒํ๊ณ ์๋ค.
Jest is a JavaScript test runner that lets you access the DOM via jsdom. While jsdom is only an approximation of how the browser works, it is often good enough for testing React components. Jest provides a great iteration speed combined with powerful features like mocking modules and timers so you can have more control over how the code executes.
React Testing Library is a set of helpers that let you test React components without relying on their implementation details. This approach makes refactoring a breeze and also nudges you towards best practices for accessibility. Although it doesnโt provide a way to โshallowlyโ render a component without its children, a test runner like Jest lets you do this by mocking.
Jest์ React Testing Library๋ฅผ ์กฐํฉํ๋ฉด ๋ค์ํ ์ปดํฌ๋ํธ๋ค์ ์ฝ๊ฒ ํ
์คํ
ํ ์ ์๋ค. ํนํ ์ปดํฌ๋ํธ ์์ ๋ค์ํ ํจ์๋ค์ ํ
์คํ
ํ ๋, mocking
์ ํตํด์ ํจ์์ ์๋์ ์ฝ๊ฒ ํ
์คํ
ํ ์ ์์๋ค.
ํ ์คํธ ์ฝ๋
// TodoFilters.test.ts
import React from 'react';
import { render, fireEvent, screen } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import prepareReduxWrapper from '@/lib/prepareReduxWrapper';
import TodoFilters from '@/components/TodoFilters';
describe('TodoFilters', () => {
const setup = () => {
const [Wrapper, store] = prepareReduxWrapper();
render(
<Wrapper>
<TodoFilters />
</Wrapper>
);
return { store };
};
it('submit new todo', async () => {
setup();
const allButton = await screen.findByText('์ ์ฒด');
expect(allButton).toBeDisabled();
const doneButton = await screen.findByText('์๋ฃ');
fireEvent.click(doneButton);
expect(doneButton).toBeDisabled();
const undoneButton = await screen.findByText('๋ฏธ์๋ฃ');
fireEvent.click(undoneButton);
expect(undoneButton).toBeDisabled();
});
});
์์ ํ
์คํธ์ฝ๋๋ TodoFilters
์ปดํฌ๋ํธ์์์ 3๊ฐ์ง ๋ฒํผ์ ํ
์คํธํ๋ ์ฝ๋์ด๋ค. ์ดํด๋ณด๋ฉด ์ ์ฒด, ์๋ฃ, ๋ฏธ์๋ฃ ๋ฒํผ 3๊ฐ์ง๊ฐ ์๊ณ ํด๋ฆญ๋ ๋ฒํผ์ด disabled๋๋์ง ํ
์คํ
ํ์๋ค.
์ด์ฒ๋ผ React-testing-library
๋ฅผ ์ฌ์ฉํ๋ฉด ์ ์ ํ
์คํ
๋ฟ๋ง ์๋๋ผ ๋์ ํ
์คํ
๊น์ง ์ฝ๊ฒ ์์ฑํ ์ ์๋ค.
React-testing-library ์ฃผ์ API
render
render
๋ DOM์ ์ปดํฌ๋ํธ๋ฅผ ๋๋๋ง ํด์ฃผ๋ ํจ์์ด๋ค. ์ธ์๋ก ๋๋๋งํ React ์ปดํฌ๋ํธ๋ฅผ ๋ฐ์ผ๋ฉฐ, React Testing Library๊ฐ ์ ๊ณตํ๋ ๋ชจ๋ ์ฟผ๋ฆฌํจ์์ ๊ธฐํ ์ ํธ๋ฆฌํฐ ํจ์๋ฅผ ๋ด๊ณ ์๋ ๊ฐ์ฒด๋ฅผ ๋ฆฌํดํ๋ค. ๋ฐ๋ผ์ ์๋์๊ฐ์ด ์ฌ์ฉํ์ฌ ์ํ๋ ์ฟผ๋ฆฌํจ์๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
import { render } from "@testing-library/react";
...
it("text testing", () => {
const wrarpper = render(<TodoFilters/>)
expect(wrapper.getByText('abcd')).toBeInTheDocument()
);
})
it("image testing", () => {
const { getByAltText } = render(<NotFound path="/abc" />);
// ์ด๋ฏธ์ง๋ alt ์์ฑ๊ฐ์ ์ด์ฉํ๋ getAltText ์ฟผ๋ฆฌํจ์๋ฅผ ์ฌ์ฉํ๋ค.
const image = getByAltText("404");
expect(image).toHaveAttribute(
"src",
"https://media.giphy.com/media/14uQ3cOFteDaU/giphy.gif"
);
});
ํน์ ์๋์ฒ๋ผ ๊ตฌ์กฐ๋ถํดํ ๋น์ผ๋ก ์ฌ์ฉํ ์ฟผ๋ฆฌํจ์๋ง์ ์ป์ด์ฌ ์๋ ์๋ค.
const { getByText, getByLabelText, getByPlaceholderText } = render(<YourComponent />)
์ฟผ๋ฆฌํจ์๋ getByXxx()
, queryByXxx()
, findByXxx()
๋ฑ ๋ค์ํ๋ฉฐ ์ด๊ณณ์์ ํ์ธ ๊ฐ๋ฅํ๋ค.
fireEvent
fireEvent
๊ฐ์ฒด๋ ํน์ ์ด๋ฒคํธ๋ฅผ ๋ฐ์์ํค๊ธฐ ์ํ ์ด๋ฒคํธ ํจ์๋ค์ ๋ด๊ณ ์๋ค. ๋ณดํต ์์์ ์ค๋ช
ํ ๋ค์ํ ์ฟผ๋ฆฌํจ์๋ก ์ด๋ฒคํธ ๋์์ ์ค์ ํ๊ณ change
, click
๋ฑ์ ์ด๋ฒคํธ๋ฅผ ์๋์์ผ ํ
์คํ
ํ๋ค.
import { render, fireEvent } from "@testing-library/react";
...
const button = getByText("๋ก๊ทธ์ธ");
const email = getByLabelText("์ด๋ฉ์ผ");
const password = getByLabelText("๋น๋ฐ๋ฒํธ");
fireEvent.change(email, { target: { value: "user@test.com" } });
fireEvent.change(password, { target: { value: "Test1234" } });
fireEvent.click(button);
...
๐ ์ฐธ๊ณ
'๊ฐ์ธ๊ณต๋ถ > TDD' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
React Testing: Hooks testing (0) | 2021.11.21 |
---|---|
React Testing: Reducer testing (with Redux) (0) | 2021.11.17 |
Typescript, Jestํ๊ฒฝ์์ alias์ ์ฉํ๊ธฐ (์ ๋๊ฒฝ๋ก import) (0) | 2021.10.31 |
jest ํ๊ฒฝ์์ import ์ฌ์ฉ ์ค์ ํ๊ธฐ(typescript) (0) | 2021.10.19 |
Jest ์ด๊ธฐํ๊ฒฝ ์ค์ ์์ ์๋ฌํธ๋ค๋ง (0) | 2021.09.13 |