์ฐํ ์ฝ 6๊ธฐ ํ๋ฆฌ์ฝ์ค 2์ฃผ์ฐจ์ ์ ์ด๋ค๋ฉด์
ํ ์คํธ ์ฝ๋ ์์ฑ์ ์ํด ๊ธฐ๋ณธ์ ์ธ Jest ๋ฌธ๋ฒ์ ์ ๋ฆฌํด๋ณด์๋ค.
npm init
npm install jest --save-dev
npm install jest @types/jest --save-dev
"scripts": {
"test": "jest"
},
jest๋ test ํด๋ ์์ ๋ฃ์ ํ์ผ๋ค,
.test.js
,.spec.js
ํ์์ ํ์ผ๋ค์ ์๋์ผ๋ก test ์ฝ๋๋ก ์ธ์ํ๋ค.
test ๋ฐ it: Jest์์๋ test์ it์ด ๋์ผํ ๊ธฐ๋ฅ์ ์ํํ๋ค. ๋ ํจ์ ๋ชจ๋ ๋จ์ผ ํ ์คํธ ์ผ์ด์ค๋ฅผ ์ ์ํ๋ค.
// test ํจ์ ์ฌ์ฉ ์
test('๋ ์ซ์์ ํฉ', () => {
expect(1 + 2).toBe(3);
});
// it ํจ์ ์ฌ์ฉ ์
it('๊ฐ์ฒด ํ ๋น ํ์ธ', () => {
const obj = {};
expect(obj).toEqual({});
});
๊ตฌ์กฐ: describe
๋ธ๋ก์ ์ฌ์ฉํ์ฌ ๊ด๋ จ ํ
์คํธ ์ผ์ด์ค๋ฅผ ๊ทธ๋ฃนํํ๋ค. ์ด๋ ํ
์คํธ๊ฐ ์ด๋ค ๋ชจ๋์ด๋ ๊ธฐ๋ฅ์ ๊ด๋ จ๋์ด ์๋์ง ๋ช
ํํ๊ฒ ํํํ๋ ๋ฐ ๋์์ด ๋๋ค.
// describe ๋ธ๋ก ์ฌ์ฉ ์
describe('String ๊ด๋ จ ํ
์คํธ', () => {
test('๋ฌธ์์ด ํฉ์น๊ธฐ', () => {
expect('Hello' + 'World').toBe('HelloWorld');
});
it('๋ฌธ์์ด ๊ธธ์ด', () => {
expect('Hello'.length).toEqual(5);
});
});
์ฌ์ฉ ๋ชฉ์ : ๊ณตํต๋ ์ค๋น ์์
์ด๋ ์ ๋ฆฌ ์์
์ ์ํด ์ฌ์ฉ๋๋ค.
- beforeEach
: ๊ฐ ํ
์คํธ๊ฐ ์คํ๋๊ธฐ ์ ์ ์คํ๋๋ค.
- afterEach
: ๊ฐ ํ
์คํธ๊ฐ ์คํ๋ ํ์ ์คํ๋๋ค.
- beforeAll
: ๋ชจ๋ ํ
์คํธ๊ฐ ์คํ๋๊ธฐ ์ ์ ๋จ ํ ๋ฒ๋ง ์คํ๋๋ค.
- afterAll
: ๋ชจ๋ ํ
์คํธ๊ฐ ์คํ๋ ํ์ ๋จ ํ ๋ฒ๋ง ์คํ๋๋ค.
// before์ after ํ
์ฌ์ฉ ์
describe('Array ๊ด๋ จ ํ
์คํธ', () => {
let array;
beforeEach(() => {
array = [1, 2, 3];
});
afterEach(() => {
array = [];
});
test('๋ฐฐ์ด ์์ ์ถ๊ฐ', () => {
array.push(4);
expect(array).toEqual([1, 2, 3, 4]);
});
it('๋ฐฐ์ด ์์ ์ ๊ฑฐ', () => {
array.pop();
expect(array).not.toContain(3);
});
});
test.only
๋๋ it.only
๋ฅผ ์ฌ์ฉํ์ฌ, ํน์ ํ
์คํธ ๋๋ ํ
์คํธ ๊ทธ๋ฃน๋ง ์คํํ ์ ์๋ค.
toEqual vs toBe: toEqual
์ ๊ฐ์ฒด์ ๋ด์ฉ์ด ๊ฐ์์ง ํ์ธํ๊ณ , toBe
๋ ๊ฐ์ ๊ฐ์ฒด์ธ์ง (์ฆ, ๋์ผํ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๋ฅผ ๊ฐ๋ฆฌํค๋์ง) ํ์ธํ๋ค.
test('๊ฐ์ฒด ๋ด์ฉ ๋น๊ต', () => {
const obj = { a: 1, b: 2 };
expect(obj).toEqual({ a: 1, b: 2 });
expect(obj).not.toBe({ a: 1, b: 2 }); // toBe๋ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๊น์ง ๋น๊ตํ๊ธฐ ๋๋ฌธ์ ์คํจ
});
toBeNull, toBeUndefined, toBeTruthy, toBeFalsy:
test('null ๊ฒ์ฌ', () => {
const n = null;
expect(n).toBeNull();
expect(n).toBeDefined();
expect(n).not.toBeUndefined();
expect(n).not.toBeTruthy();
expect(n).toBeFalsy();
});
toBeGreaterThan, toBeLessThan: ์ซ์ ๋น๊ต๋ฅผ ์ํ ๋จ์ธ๋ค์ด๋ค.
test('์ซ์ ๋น๊ต', () => {
const value = 2 + 2;
expect(value).toBeGreaterThan(3);
expect(value).toBeLessThan(5);
expect(value).toBe(4);
expect(value).toEqual(4);
});
toBeCloseTo : ๋ถ๋ ์์์ ์ซ์๋ค์ ๋น๊ตํ๋ค.
JavaScript์ ๋ถ๋ ์์์ ๊ณ์ฐ ์ค์ฐจ ๋๋ฌธ์ ์ ์ฉํ๋ค.
์๋ฅผ ๋ค์ด, 0.2 + 0.1์ด ์ ํํ 0.3์ด ์๋ ๋, ์ด ๋จ์ธ์ ๋ ์ซ์๊ฐ ์ถฉ๋ถํ ๊ฐ๊น์ด์ง๋ฅผ ํ๋จํ๋ค. ๋ ๋ฒ์งธ ์ธ์๋ก ์์์ ์๋ ์๋ฆฟ์๋ฅผ ์ง์ ํด ๋น๊ต ์ ๋ฐ๋๋ฅผ ์กฐ์ ํ๋ค.
test("adding floats", () => {
const value = 0.1 + 0.2;
expect(value).toBeCloseTo(0.3);
expect(value).toBeCloseTo(0.29); // fail
expect(value).toBeCloseTo(0.299); // pass
});
toBeCloseTo : ๋ ๋ฒ์งธ ์ธ์๋ก ์์์ ์๋ ์๋ฆฟ์๋ฅผ ์ง์ ํ ์ ์์ด, ๋น๊ต์ ์ ๋ฐ๋๋ฅผ ์กฐ์ ํ ์ ์๋ค.
์๋ฅผ ๋ค์ด, ๋ ์ซ์๊ฐ ์์์ ์๋ ๋ ์๋ฆฌ๊น์ง๋ง ๋น๊ตํ๋ ค๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉํ๋ค.
expect(0.223).toBeCloseTo(0.22, 2); // pass
toMatch: ์ ๊ท์์ ์ฌ์ฉํด ๋ฌธ์์ด์ ํ ์คํธํ ์ ์๋ค.
test('๋ฌธ์์ด์ ํน์ ๋ฌธ์๊ฐ ์๋์ง ํ์ธ', () => {
expect('team').not.toMatch(/I/);
expect('Christoph').toMatch(/stop/);
});
toContain: ๋ฐฐ์ด์ด๋ ๋ฐ๋ณต ๊ฐ๋ฅ ๊ฐ์ฒด๊ฐ ํน์ ํญ๋ชฉ์ ํฌํจํ๋์ง ํ์ธํ๋ค.
test('๋ฐฐ์ด์ ํน์ ์์๊ฐ ์๋์ง ํ์ธ', () => {
const shoppingList = ['diapers', 'kleenex', 'trash bags', 'paper towels', 'milk'];
expect(shoppingList).toContain('milk');
expect(new Set(shoppingList)).toContain('milk');
});
toContainEqual : ๋ฐฐ์ด์ด ํน์ ์์๋ฅผ ํฌํจํ๊ณ ์๋์ง ํ์ธํ๋ค. ์์๊ฐ ๊ฐ์ฒด์ธ ๊ฒฝ์ฐ์๋ ์ ํํ ์ผ์น ์ฌ๋ถ๋ฅผ ๊ฒ์ฌํ๋ค.
// ๋ฐฐ์ด ์์ { name: "Bob" } ๊ฐ์ฒด๊ฐ ํฌํจ๋์ด ์๋์ง๋ฅผ ํ์ธ
expect([{ name: "Alice" }, { name: "Bob" }]).toContainEqual({ name: "Bob" });
toThrow: ํจ์๊ฐ ํน์ ์์ธ๋ฅผ ๋์ง๋์ง ํ ์คํธํ๋ค.
function compileAndroidCode() {
throw new Error('you are using the wrong JDK');
}
test('ํน์ ์ค๋ฅ๋ฅผ ๋์ง๋์ง ํ์ธ', () => {
expect(() => compileAndroidCode()).toThrow();
expect(() => compileAndroidCode()).toThrow(Error);
// ์ค๋ฅ ๋ฉ์์ง๋ ์ ๊ท์์ ์ด์ฉํ ์ค๋ฅ ๊ฒ์ฌ
expect(() => compileAndroidCode()).toThrow('you are using the wrong JDK');
expect(() => compileAndroidCode()).toThrow(/JDK/);
});
jest.fn()
: ๋ชจ์ ํจ์๋ฅผ ์์ฑํ๊ณ , ํธ์ถ ์ ๋ณด๋ฅผ ์ถ์ ํ๋ค.test('๋ชจ์ ํจ์ ์์ ', () => {
const mockFn = jest.fn();
mockFn(1);
expect(mockFn).toHaveBeenCalled();
expect(mockFn).toHaveBeenCalledWith(1);
});
ํจ์ ๋ชจ์ : ์ธ๋ถ ํจ์ ํธ์ถ์ ์ํฅ์ ์ค์ด๊ธฐ ์ํด, ์ค์ ํจ์ ๋์ ๋ชจ์ ํจ์๋ฅผ ์ฌ์ฉํ๋ค.
test('๋ชจ์ ๊ตฌํ ์์ ', () => {
const mockFn = jest.fn().mockImplementation(scalar => 42 + scalar);
// ๋๋ jest.fn(scalar => 42 + scalar);
expect(mockFn(1)).toBe(43);
});
๋ชจ์ ๊ตฌํ : mockImplementation()์ ์ฌ์ฉํ์ฌ ๋ชจ์ ํจ์์ ๊ตฌ์ฒด์ ์ธ ๋์์ ์ ์ํ ์ ์๋ค.
test('๋ชจ์ ๊ตฌํ ์์ ', () => {
const mockFn = jest.fn().mockImplementation(scalar => 42 + scalar);
// ๋๋ jest.fn(scalar => 42 + scalar);
expect(mockFn(1)).toBe(43);
});
toHaveBeenCalled
, toHaveBeenCalledTimes
: ํจ์๊ฐ ํธ์ถ๋์๋์ง, ํน์ ํ์๋งํผ ํธ์ถ๋์๋์ง ํ์ธํ๋ค.
test('๋ชจ์ ํจ์ ํธ์ถ ์ฌ๋ถ ๋ฐ ํ์ ๊ฒ์ฆ', () => {
const mockFn = jest.fn();
mockFn();
mockFn([1, 2, 3]);
// ํจ์๊ฐ ํธ์ถ๋์๋์ง
expect(mockFn).toHaveBeenCalled();
// ์ ํํ 2๋ฒ ํธ์ถ๋์๋์ง
expect(mockFn).toHaveBeenCalledTimes(2);
// ๋ ๋ฒ์งธ ํธ์ถ ๋ ์ฒซ ๋ฒ์งธ ์ธ์๊ฐ [1, 2, 3]์ด์๋์ง
expect(mockFn.mock.calls[1][0]).toEqual([1, 2, 3]);
});
resolves, rejects: Promise๊ฐ ํด๊ฒฐ๋๊ฑฐ๋ ๊ฑฐ๋ถ๋ ๋์ ์ํ๋ฅผ ํ ์คํธํ๋ค.
test('Promise๊ฐ ์ฑ๊ณต์ ์ผ๋ก ํด๊ฒฐ๋๋์ง ํ์ธ', () => {
return expect(Promise.resolve('์ฑ๊ณต')).resolves.toBe('์ฑ๊ณต');
});
test('Promise๊ฐ ์คํจํ๋ฉฐ ์ค๋ฅ๋ฅผ ๋์ง๋์ง ํ์ธ', () => {
return expect(Promise.reject(new Error('์คํจ'))).rejects.toThrow('์คํจ');
});
๋น๋๊ธฐ ํจ์: async
ํจ์ ๋ด์์ await expect()
์ ์ฌ์ฉํ์ฌ ๋น๋๊ธฐ ํจ์๋ฅผ ํ
์คํธํ๋ค.
test('async/await์ ์ฌ์ฉํ ๋น๋๊ธฐ ํ
์คํธ', async () => {
await expect(Promise.resolve('์ฑ๊ณต')).resolves.toBe('์ฑ๊ณต');
await expect(Promise.reject(new Error('์คํจ'))).rejects.toThrow('์คํจ');
});