๐ญ Jest: JavaScript ํ ์คํ ์ ๊ฐ๋ ฅํ ๋๊ตฌ
Jest๋ JavaScript ํ ์คํธ ํ๋ ์์ํฌ๋ก, React์ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ Node.js ๊ธฐ๋ฐ ํ๋ก์ ํธ์์ ์ฌ์ฉํ๊ธฐ ์ ํฉํ ํ ์คํ ๋๊ตฌ์ ๋๋ค. Facebook(ํ์ฌ Meta)์์ ๊ฐ๋ฐํ์ผ๋ฉฐ, ๋น ๋ฅธ ์คํ ์๋, ๊ฐํธํ ์ค์ , ๊ทธ๋ฆฌ๊ณ ์ง๊ด์ ์ธ ์ฌ์ฉ๋ฒ์ผ๋ก ํ๋ก ํธ์๋์ ๋ฐฑ์๋ ๋ชจ๋์์ ๋๋ฆฌ ์ฌ์ฉ๋ฉ๋๋ค.
์ด๋ฒ ๊ธ์์๋ Jest๊ฐ ๋ฌด์์ธ์ง, ์ฃผ์ ๊ธฐ๋ฅ, ์ฅ์ , ๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ, ๊ทธ๋ฆฌ๊ณ ์ค๋ฌด์์ ์ ์ฉํ ํ๊น์ง ํญ๋๊ฒ ๋ค๋ค๋ณด๊ฒ ์ต๋๋ค!
๐ Jest๋ ๋ฌด์์ธ๊ฐ?
Jest๋ ๋จ์ ํ ์คํธ, ํตํฉ ํ ์คํธ, ์ค๋ ์ท ํ ์คํธ๋ฅผ ๊ฐํธํ๊ฒ ์์ฑํ๊ณ ์คํํ ์ ์๋ JavaScript ํ ์คํธ ํ๋ ์์ํฌ์ ๋๋ค.
โข ํ ์คํธ ์คํ ํ๊ฒฝ: Jest๋ ํ ์คํธ๋ฅผ ์คํํ๊ธฐ ์ํ ์์ฒด์ ์ธ ํ๊ฒฝ์ ์ ๊ณตํ๋ฉฐ, ์ถ๊ฐ ์ค์ ์์ด ๋ฐ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
โข React์ ํธํ์ฑ: Jest๋ React ํ๋ก์ ํธ์ ํนํ ์ ๋ง์ผ๋ฉฐ, React ์ปดํฌ๋ํธ์ ํ ์คํธ๋ฅผ ์ฝ๊ฒ ์์ฑํ ์ ์์ต๋๋ค.
โข ๊ฐ๋ ฅํ ๊ธฐ๋ฅ ์ ๊ณต: ์ค๋ ์ท ํ ์คํธ, ๋ชจ์ ํจ์(Mock Function), ์ฝ๋ ์ปค๋ฒ๋ฆฌ์ง ๋ฆฌํฌํธ ๋ฑ์ด ๋ด์ฅ๋์ด ์์ต๋๋ค.
โจ Jest์ ์ฃผ์ ๊ธฐ๋ฅ
1. Zero Configuration
โข ์ค์น๋ง์ผ๋ก ๋๋ถ๋ถ์ JavaScript ํ๋ก์ ํธ์์ ๋ฐ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
โข ๋ณ๋์ ์ค์ ํ์ผ ์์ด ๋น ๋ฅด๊ฒ ์์ ๊ฐ๋ฅ.
2. ์ค๋ ์ท ํ ์คํธ
โข UI ์ปดํฌ๋ํธ๊ฐ ๋ณ๊ฒฝ๋์๋์ง ํ์ธํ ๋ ์ฌ์ฉ๋ฉ๋๋ค.
โข DOM ๊ตฌ์กฐ๋ฅผ ์ค๋ ์ท์ผ๋ก ์ ์ฅํ๊ณ , ์ดํ ํ ์คํธ์์ ์ด๋ฅผ ๋น๊ตํฉ๋๋ค.
3. Mocking
โข ์์กด์ฑ์ ๊ฒฉ๋ฆฌํ์ฌ ํ ์คํธํ ์ ์๋๋ก Mock ํจ์์ Mock ๋ชจ๋์ ์ ๊ณตํฉ๋๋ค.
โข API ์์ฒญ์ด๋ DB ํธ์ถ ๊ฐ์ ์ธ๋ถ ์์กด์ฑ์ ์ค์ ๋ก ์คํํ์ง ์๊ณ ๋ ํ ์คํธ ๊ฐ๋ฅ.
4. ์ฝ๋ ์ปค๋ฒ๋ฆฌ์ง
โข ํ ์คํธ๊ฐ ์ฝ๋์ ์ด๋ ๋ถ๋ถ์ ๊ฒ์ฆํ๋์ง ์๊ฐ์ ์ผ๋ก ๋ณด์ฌ์ฃผ๋ ์ปค๋ฒ๋ฆฌ์ง ๋ฆฌํฌํธ๋ฅผ ์์ฑํฉ๋๋ค.
โข --coverage ํ๋๊ทธ๋ฅผ ์ฌ์ฉํ๋ฉด ์ฆ์ ํ์ธ ๊ฐ๋ฅ.
5. Watch ๋ชจ๋
โข ํ์ผ์ด ๋ณ๊ฒฝ๋ ๋๋ง๋ค ์๋์ผ๋ก ํ ์คํธ๋ฅผ ์ฌ์คํํฉ๋๋ค.
โข ๊ฐ๋ฐ ์ค ๋น ๋ฅธ ํผ๋๋ฐฑ์ ์ ๊ณต.
6. ๊ฐ๋ ฅํ ๋งค์ฒ(Matcher)
โข expect๋ฅผ ํตํด ๋ค์ํ ํํ์ ํ ์คํธ๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
โข ์ซ์, ๊ฐ์ฒด, ๋ฐฐ์ด, ๋น๋๊ธฐ ์์ ๋ฑ์ ์ง๊ด์ ์ผ๋ก ๊ฒ์ฆํ ์ ์๋ API๋ฅผ ์ ๊ณตํฉ๋๋ค.
๐ฆ Jest ์ค์น์ ๊ธฐ๋ณธ ์ค์
1๏ธโฃ Jest ์ค์น
Jest๋ฅผ ์ค์นํ๋ ค๋ฉด Node.js ํ๋ก์ ํธ์ ๋ค์ ๋ช ๋ น์ด๋ฅผ ์คํํ์ธ์.
npm install --save-dev jest
2๏ธโฃ Jest ์ค์
๋๋ถ๋ถ์ ํ๋ก์ ํธ๋ ๋ณ๋ ์ค์ ์์ด๋ ์คํํ ์ ์์ง๋ง, ์ค์ ํ์ผ์ด ํ์ํ ๊ฒฝ์ฐ jest.config.js๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
module.exports = {
testEnvironment: 'node', // ํ
์คํธ ํ๊ฒฝ (jsdom, node ๋ฑ)
collectCoverage: true, // ์ฝ๋ ์ปค๋ฒ๋ฆฌ์ง ํ์ฑํ
coverageDirectory: 'coverage', // ์ปค๋ฒ๋ฆฌ์ง ๋ฆฌํฌํธ ๋๋ ํ ๋ฆฌ
};
๐ ๏ธ Jest ์ฌ์ฉ๋ฒ: ๊ธฐ๋ณธ ์์
1๏ธโฃ ๋จ์ ํ ์คํธ
Jest์ ๊ธฐ๋ณธ์ ์ธ ํ ์คํธ๋ test ๋๋ it ๋ฉ์๋๋ฅผ ์ฌ์ฉํฉ๋๋ค.
function add(a, b) {
return a + b;
}
test('add ํจ์๋ ๋ ์ซ์์ ํฉ์ ๋ฐํํด์ผ ํ๋ค', () => {
expect(add(1, 2)).toBe(3);
});
2๏ธโฃ ๋น๋๊ธฐ ์ฝ๋ ํ ์คํธ
Jest๋ async/await ๋๋ done ์ฝ๋ฐฑ์ ์ฌ์ฉํด ๋น๋๊ธฐ ์ฝ๋๋ฅผ ์ฝ๊ฒ ํ ์คํธํ ์ ์์ต๋๋ค.
function fetchData() {
return new Promise(resolve => setTimeout(() => resolve('๋ฐ์ดํฐ ๋ก๋ ์๋ฃ!'), 100));
}
test('๋น๋๊ธฐ ํจ์ fetchData ํ
์คํธ', async () => {
const data = await fetchData();
expect(data).toBe('๋ฐ์ดํฐ ๋ก๋ ์๋ฃ!');
});
3๏ธโฃ Mock ํจ์
Mock ํจ์๋ ์์กด์ฑ์ ๊ฒฉ๋ฆฌํ๊ณ , ํจ์ ํธ์ถ ์ฌ๋ถ์ ํธ์ถ๋ ์ธ์๋ฅผ ํ์ธํ๋ ๋ฐ ์ ์ฉํฉ๋๋ค.
const mockFn = jest.fn();
mockFn('hello');
expect(mockFn).toHaveBeenCalledWith('hello');
๐งฉ Jest์ ์ค๋ ์ท ํ ์คํธ
์ค๋ ์ท ํ ์คํธ๋ UI๊ฐ ๋ณ๊ฒฝ๋์๋์ง ํ์ธํ๋ ๋ฐ ์ ์ฉํฉ๋๋ค.
const renderer = require('react-test-renderer');
const MyComponent = () => <div>Hello Jest!</div>;
test('MyComponent ์ค๋
์ท ํ
์คํธ', () => {
const tree = renderer.create(<MyComponent />).toJSON();
expect(tree).toMatchSnapshot();
});
โข Jest๋ ์ค๋ ์ท์ ์ ์ฅํ๊ณ , ์ดํ ํ ์คํธ์์ ์ด๋ฅผ ๋น๊ตํ์ฌ ๋ณ๊ฒฝ ์ฌํญ์ ๊ฐ์งํฉ๋๋ค.
๐ก Jest๋ฅผ ํ์ฉํ ํ๊ณผ ํธ๋ฆญ
1. ํ ์คํธ ํ์ผ ๊ตฌ์กฐ
โข ํ ์คํธ ํ์ผ์ ์ผ๋ฐ์ ์ผ๋ก __tests__ ๋๋ ํ ๋ฆฌ์ ๋๊ฑฐ๋, .test.js ๋๋ .spec.js ํ์ฅ์๋ฅผ ์ฌ์ฉํฉ๋๋ค.
2. ์ปค์คํ ๋งค์ฒ ์ถ๊ฐ
โข expect.extend๋ฅผ ์ฌ์ฉํด ๊ณ ์ ํ ํ ์คํธ ๋งค์ฒ๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
expect.extend({
toBeEven(received) {
const pass = received % 2 === 0;
if (pass) {
return {
message: () => `expected ${received} not to be even`,
pass: true,
};
} else {
return {
message: () => `expected ${received} to be even`,
pass: false,
};
}
},
});
3. ๋น๋๊ธฐ ์์ ๋๋ฒ๊น
โข jest.useFakeTimers์ jest.advanceTimersByTime์ ํ์ฉํด ํ์ด๋จธ ๊ธฐ๋ฐ ๋น๋๊ธฐ ์ฝ๋๋ฅผ ๋๋ฒ๊น ํฉ๋๋ค.
jest.useFakeTimers();
test('ํ์ด๋จธ ํ
์คํธ', () => {
const mockFn = jest.fn();
setTimeout(mockFn, 1000);
jest.advanceTimersByTime(1000);
expect(mockFn).toHaveBeenCalled();
});
๐ Jest์ ์ฅ์
1๏ธโฃ ๊ฐํธํจ: ์ถ๊ฐ ์ค์ ์์ด ๋ฐ๋ก ์ฌ์ฉํ ์ ์๋ ํ ์คํ ํ๊ฒฝ ์ ๊ณต.
2๏ธโฃ React ์นํ์ : React์ ์ปดํฌ๋ํธ ํ ์คํธ์ ์ค๋ ์ท ๊ธฐ๋ฅ ์ง์.
3๏ธโฃ ๋น ๋ฅธ ์คํ: ํ ์คํธ ๋ณ๋ ฌ ์ฒ๋ฆฌ์ ์บ์ฑ์ ํตํด ๋น ๋ฅด๊ฒ ์คํ.
4๏ธโฃ ํ๋ฐํ ์ปค๋ฎค๋ํฐ: ํ๋ถํ ๋ฌธ์์ ๋ค์ํ ํ๋ฌ๊ทธ์ธ ์ ๊ณต.
๐ญ ๊ฒฐ๋ก
Jest๋ JavaScript์ React ์ ํ๋ฆฌ์ผ์ด์ ์ ํ ์คํธ๋ฅผ ์์ฑํ๊ณ ์คํํ๋ ๋ฐ ๊ฐ๋ ฅํ ๋๊ตฌ์ ๋๋ค. ๊ฐ๋จํ ์ค์ ๊ณผ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ ๋๋ถ์ ์ด๋ณด์๋ถํฐ ์๋ จ๋ ๊ฐ๋ฐ์๊น์ง ๋ชจ๋์๊ฒ ์ฌ๋๋ฐ๋ ํ๋ ์์ํฌ์ฃ . ํ ์คํธ๋ฅผ ํตํด ์ ํ๋ฆฌ์ผ์ด์ ์ ์์ ์ฑ๊ณผ ์ ๋ขฐ์ฑ์ ๋์ด๊ณ , ๋ณด๋ค ๋์ ์ฌ์ฉ์ ๊ฒฝํ์ ์ ๊ณตํ์ธ์!
๐ท ์ ์ค์ ๊ฐ๋ฐ์๊ฐ ๋์ด๋ด ์๋น! ๐ท