1. TDD

TDD ์— ๋Œ€ํ•ด์„œ ์ฃผ์˜ํ•  ์  ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค๊ณ  ํ•ด์„œ TDD ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. TDD Cycle ์— ๋”ฐ๋ผ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ๋จผ์ € ์ž‘์„ฑํ•˜๊ณ , ๊ตฌํ˜„ํ•˜๊ณ , ๋ฆฌํŒฉํ„ฐ๋ง ํ•˜๋Š” ๊ณผ์ •์„ ์—„๊ฒฉํ•˜๊ฒŒ ์ง€์ผœ์„œ ๊ฐœ๋ฐœ์„ ์ง„ํ–‰ํ•ด์•ผ TDD ๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. TDD ๋Š” ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ๊ณผ ๋ณ„๊ฐœ๋กœ ๋”ฐ๋กœ ์—ฐ์Šต์ด ํ•„์š”ํ•˜๊ณ  ์Šต๊ด€์„ ๋“ค์—ฌ์•ผํ•˜๋Š” ๋ถ„์•ผ ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  TDD ๋ฅผ ์ž˜ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ๋ฒ• ์ž์ฒด๋ถ€ํ„ฐ ๊ณต๋ถ€๋ฅผ ํ•˜์…”์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹น์žฅ์€ TDD ๋ณด๋‹ค ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ์— ์ต์ˆ™ํ•ด์ง€๊ณ  ์–ด๋–ป๊ฒŒ ํ•˜๋ฉด ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž˜ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์„๊นŒ์— ์ดˆ์ ์„ ๋งž์ถฐ ๊ณต๋ถ€ํ•˜์‹œ๋ฉด ์ข‹์Šต๋‹ˆ๋‹ค.

TDD

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ๋จผ์ € ์ž‘์„ฑํ•˜๋Š”, ์ฆ‰ ๊ตฌํ˜„๋ณด๋‹ค ์ธํ„ฐํŽ˜์ด์Šค์™€ ์ŠคํŽ™์„ ๋จผ์ € ์ •์˜ํ•จ์œผ๋กœ์จ ๊ฐœ๋ฐœ์„ ์ง„ํ–‰ํ•˜๋Š” ๋ฐฉ์‹

์งง์€ ๋‹จ์œ„์˜ TDD Cycle์€ ๋ฐ˜๋ณตํ•˜๋ฉด์„œ ๊ฐœ๋ฐœ์„ ์ง„ํ–‰

TDD Cycle

  1. Red : ์‹คํŒจํ•˜๋Š” ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑ

  2. Green : ์žฌ๋นจ๋ฆฌ ํ…Œ์ŠคํŠธ๋ฅผ ํ†ต๊ณผ์‹œํ‚ด

  3. Refactor : ๋ฆฌํŒฉํ† ๋ง์„ ํ†ตํ•ด์„œ ์ฝ”๋“œ๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋งŒ๋“ฆ

Jest

Test Matcher : toBe()์™€ ๊ฐ™์ด ๊ธฐ๋Œ€๊ฐ’์„ ๋น„๊ตํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ํ•จ์ˆ˜. toBe()๋Š” ์ˆซ์ž๋‚˜ ๋ฌธ์ž์™€ ๊ฐ™์€ ๊ฐ์ฒด๊ฐ€ ์•„๋‹Œ ๊ธฐ๋ณธํ˜•(primitive) ๊ฐ’์„ ๋น„๊ตํ•  ๋•Œ ์‚ฌ์šฉ๋จ

toEqual()

๊ฐ์ฒด๋ฅผ ๊ฒ€์ฆํ• ๋•Œ๋Š” toBe() ๋Œ€์‹  toEqual() ์‚ฌ์šฉ

function getUser(id) {
  return {
    id,
    email: `user${id}@test.com`,
  };
}

test("return a user object", () => {
  expect(getUser(1)).toEqual({
    id: 1,
    email: `user1@test.com`,
  });
});

toBeTruthy(), toBeFalsy()

toBeTruthy()๋Š” boolean ํƒ€์ž…์ด ์•„๋‹ˆ์–ด๋„ true๋กœ ๊ฐ„์ฃผ๋˜๋ฉด ํ†ต๊ณผ๋˜๊ณ , toBeFalsy()๋Š” false๋กœ ๊ฐ„์ฃผ๋˜๋ฉด ํ†ต๊ณผ

test("number 0 is falsy but string 0 is truthy", () => {
  expect(0).toBeFalsy();
  expect("0").toBeTruthy();
});

toHaveLength(), toContain()

toHaveLength() : ๋ฐฐ์—ด์˜ ๊ธธ์ด๋ฅผ ์ฒดํฌ

toContain() : ํŠน์ • ์›์†Œ๊ฐ€ ๋ฐฐ์—ด์— ๋“ค์–ด์žˆ๋Š”์ง€๋ฅผ ํ…Œ์ŠคํŠธ

test("array", () => {
  const colors = ["Red", "Yellow", "Blue"];
  expect(colors).toHaveLength(3);
  expect(colors).toContain("Yellow");
  expect(colors).not.toContain("Green");
});

Matcher ์•ž์— not Matcher๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ถˆ๋งŒ์กฑํ•˜๋Š” ๊ฒฝ์šฐ๋ฅผ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์Œ

toMatch()

์ •๊ทœ์‹ ๊ธฐ๋ฐ˜์˜ ๋ฌธ์ž์—ด ํ…Œ์ŠคํŠธ

test("string", () => {
  expect(getUser(1).email).toBe("user1@test.com");
  expect(getUser(2).email).toMatch(/.*test.com$/);
});

toThrow()

์˜ˆ์™ธ๋ฐœ์ƒ ์—ฌ๋ถ€๋ฅผ ํ…Œ์ŠคํŠธ

์ธ์ž๋กœ ๋ฌธ์ž์—ด์„ ๋„˜๊ธฐ๋ฉด ์˜ˆ์™ธ ๋ฉ”์‹œ์ง€๋ฅผ ๋น„๊ตํ•˜๊ณ  ์ •๊ทœ์‹์„ ๋„˜๊ธฐ๋ฉด ์ •๊ทœ์‹ ์ฒดํฌ๋ฅผ ํ•ด์คŒ

expect() ํ•จ์ˆ˜์— ๋„˜๊ธฐ๋Š” ๊ฒ€์ฆ ๋Œ€์ƒ์„ ํ•จ์ˆ˜๋กœ ํ•œ ๋ฒˆ ๊ฐ์‹ธ์ค˜์•ผ ํ…Œ์ŠคํŠธ ์ค‘์— ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ด ์‹คํŒจํ•˜๋Š” ๊ฒƒ์„ ๋ง‰์„ ์ˆ˜ ์žˆ์Œ

function getUser(id) {
  if (id <= 0) throw new Error("Invalid ID");
  return {
    id,
    email: `user${id}@test.com`,
  };
}

test("throw when id is non negative", () => {
  expect(() => getUser(-1)).toThrow();
  expect(() => getUser(-1)).toThrow("Invalid ID");
});

Describe - Context - it

Jest์˜ describe(), it()

describe() ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์—ฐ๊ด€๋œ ํ…Œ์ŠคํŠธ๋ฅผ ๊ทธ๋ฃนํ™”ํ•  ์ˆ˜ ์žˆ์Œ

describe("group 1", () => {
  test("test 1-1", () => {
    // ...
  });

  test("test 1-2", () => {
    // ...
  });
});

describe("group 2", () => {
  it("test 2-1", () => {
    // ...
  });

  it("test 2-2", () => {
    // ...
  });
});

it() ํ•จ์ˆ˜๋Š” test() ํ•จ์ˆ˜์™€ ์™„์ „ํžˆ ๋™์ผ

Describe - Context - It ํŒจํ„ด

  • Describe : Sum ํ•จ์ˆ˜๋Š”

  • Context : ์ž…๋ ฅ์œผ๋กœ 300๊ณผ 200์ด ์ฃผ์–ด์ง€๋ฉด

  • It : 500์„ ๋ฆฌํ„ดํ•œ๋‹ค

Describe("Sum", func() {
  Context("With 300 and 200", func() {
    It("returns 500", func() {
      Expect(Sum(300, 200)).To(Equal(500))
    })
  })

  Context("With -300 and 200", func() {
    It("returns -100", func() {
      Expect(Sum(-300, 200)).To(Equal(-100))
    })
  })
})

๋‹จ์œ„ํ…Œ์ŠคํŠธ

์‘์šฉํ”„๋กœ๊ทธ๋žจ์—์„œ ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅํ•œ ๊ฐ€์žฅ ์ž‘์€ ์†Œํ”„ํŠธ์›จ์–ด๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ์˜ˆ์ƒ๋Œ€๋กœ ๋™์ž‘ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” ํ…Œ์ŠคํŠธ

Stub

  • ์ผ๋ฐ˜์ ์ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” ํ•˜๋‚˜์˜ ๊ธฐ๋Šฅ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ๊ณผ ๋ฉ”์‹œ์ง€๋ฅผ ์ฃผ๊ณ ๋ฐ›์•„์•ผํ•จ

  • ๋‹จ์œ„ํ…Œ์ŠคํŠธ์—์„œ๋Š” ๋‹ค๋ฅธ ๊ฐ์ฒด์™€ ๋ฉ”์‹œ์ง€๋ฅผ ์ฃผ๊ณ  ๋ฐ›์„ ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค๋ฅธ ๊ฐ์ฒด ๋Œ€์‹ ์— ๊ฐ€์งœ ๊ฐ์ฒด(Mock Object)๋ฅผ ์ฃผ์ž…ํ•˜์—ฌ ์–ด๋–ค ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ผ๊ณ  ์ •ํ•ด์ง„ ๋‹ต๋ณ€์„ ์ค€๋น„์‹œ์ผœ์•ผ ํ•˜๋Š”๋ฐ ์ด๋ฅผ stub์ด๋ผ๊ณ  ํ•จ

Last updated