Front-end/Test

๐ŸŽญ Jest: JavaScript ํ…Œ์ŠคํŒ…์˜ ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ

xeunnie 2025. 3. 12. 01:00
728x90
๋ฐ˜์‘ํ˜•

๐ŸŽญ 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 ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ์‹คํ–‰ํ•˜๋Š” ๋ฐ ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. ๊ฐ„๋‹จํ•œ ์„ค์ •๊ณผ ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ ๋•๋ถ„์— ์ดˆ๋ณด์ž๋ถ€ํ„ฐ ์ˆ™๋ จ๋œ ๊ฐœ๋ฐœ์ž๊นŒ์ง€ ๋ชจ๋‘์—๊ฒŒ ์‚ฌ๋ž‘๋ฐ›๋Š” ํ”„๋ ˆ์ž„์›Œํฌ์ฃ . ํ…Œ์ŠคํŠธ๋ฅผ ํ†ตํ•ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์•ˆ์ •์„ฑ๊ณผ ์‹ ๋ขฐ์„ฑ์„ ๋†’์ด๊ณ , ๋ณด๋‹ค ๋‚˜์€ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ์ œ๊ณตํ•˜์„ธ์š”!

 

๐ŸŒท ์ „์„ค์˜ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜์–ด๋ด…์‹œ๋‹น! ๐ŸŒท

728x90
๋ฐ˜์‘ํ˜•