๐Ÿ“š ํ•˜๋ฃจ๋งŒ์— Cypress๋กœ ์ž‘์„ฑํ•˜๋Š” JS E2E ํ…Œ์ŠคํŠธ ์ฝ”๋“œ

์ด ๊ธ€์€ ๋ฉ”์ด์ปค์ค€-ํ•˜๋ฃจ๋งŒ์— Cypress๋กœ ์ž‘์„ฑํ•˜๋Š” JS E2E ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ˆ˜๊ฐ• ํ›„ ์ž‘์„ฑํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค. ๊ฐ•์˜์™€ ์ง์ ‘์ ์ธ ๊ด€๊ณ„๊ฐ€ ์žˆ๋Š” ์ •๋ณด๋Š” ์ตœ๋Œ€ํ•œ ๋ฐฐ์ œํ•˜์˜€์Šต๋‹ˆ๋‹ค.
๊ฐ„๋‹จํ•œ ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ์–ด๋–ป๊ฒŒ Cypress๋ฅผ ๋‹ค๋ฃจ๋Š”์ง€, ์™œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์•ผํ•˜๋Š”์ง€ ๋“ฑ์— ๋Œ€ํ•ด ์ •๋ฆฌํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

E2E Test๋ž€?

End-to-End ํ…Œ์ŠคํŠธ์˜ ์•ฝ์ž๋กœ ๋ง๊ทธ๋Œ€๋กœ ์‚ฌ์šฉ์ž์˜ ์ค‘์‹ฌ์—์„œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ฒ˜์Œ๋ถ€ํ„ฐ ๋๊นŒ์ง€ ๊ทธ ํ๋ฆ„์„ ํ…Œ์ŠคํŠธํ•˜๋Š” ์†Œํ”„ํŠธ์›จ์–ด ํ…Œ์ŠคํŠธ ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. E2E ํ…Œ์ŠคํŠธ๋ฅผ ํ†ตํ•ด ์‹ค์ œ ์œ ์ € ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ํ•˜๊ณ  ์ด๋ฅผ ํ†ตํ•ด ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ตฌ์„ฑ ์š”์†Œ์˜ ํ†ตํ•ฉ ๋ฐ ๋ฐ์ดํ„ฐ์˜ ๋ฌด๊ฒฐ์„ฑ์„ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Cypress๋Š” ๋ญ˜๊นŒ?

๊ฐœ๋ฐœ์ž๋Š” Cypress๋ฅผ ํ†ตํ•ด E2E ํ…Œ์ŠคํŠธ๋ฅผ ํ›จ์”ฌ ํŽธํ•˜๊ฒŒ ๊ตฌํ˜„ํ•˜๊ณ  ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋‚ด์—์„œ ์œ ์ €๊ฐ€ ์ทจํ•  ์ˆ˜ ์žˆ๋Š” ๋‹ค์–‘ํ•œ ํ–‰๋™ ๋ฐฉ์‹๊ณผ ๊ทธ ๊ฒฐ๊ณผ๊ฐ’์„ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋กœ ์ž‘์„ฑํ•˜๊ณ  ๊ฒ€์ฆํ•จ์œผ๋กœ์จ, ํ…Œ์ŠคํŠธ์— ๋“ค์–ด๊ฐ€๋Š” ์‹œ๊ฐ„์„ ๋งค์šฐ๋งค์šฐ๋งค์šฐ ์•„๋‚„ ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ, Cypress๋Š” GUI๋ฅผ ํ†ตํ•ด ๋” ์‰ฝ๊ฒŒ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๊ณ , E2E๋ฟ ์•„๋‹ˆ๋ผ ํ†ตํ•ฉ, ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๊นŒ์ง€ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ๋‹จ์œ„, ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๋Š” ๋˜ ๋ญ์ง€?

  • ๋‹จ์œ„ ํ…Œ์ŠคํŠธ : ๊ฐ€์žฅ ์ž‘์€ ๋‹จ์œ„์˜ ํ…Œ์ŠคํŠธ๋กœ, ์ฃผ๋กœ ๋ชจ๋“ˆ ์ฆ‰, ํ•จ์ˆ˜์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ๋ฅผ ๋งํ•ฉ๋‹ˆ๋‹ค. ์ž‘์„ฑ ๋น„์šฉ์ด ์ ๊ณ  ์‹คํ–‰ ์†๋„๊ฐ€ ๋น ๋ฆ…๋‹ˆ๋‹ค. ์•„๋ฌด๋ž˜๋„ ๋‹จ์œ„๊ฐ€ ๊ฐ€์žฅ ์ž‘๊ธฐ์—, ๋น ๋ฅด๊ฒŒ ๋ฌธ์ œ๋ฅผ ๋ฐœ๊ฒฌํ•˜๊ณ  ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
function example = (a, b) => a + b;
// ์ด ๋•Œ, 1๊ณผ 2๊ฐ€ ๋ณ€์ˆ˜๋กœ ๋“ค์–ด๊ฐ”์„ ๋•Œ, 3์ด ๋‚˜์˜ค๋Š”์ง€ ํ…Œ์ŠคํŠธ -> ๋‹จ์œ„ ํ…Œ์ŠคํŠธ
  • ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ : ๋ชจ๋“ˆ๊ณผ ๋ชจ๋“ˆ ๊ฐ„์˜ ๊ด€๊ณ„๋ฅผ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ฒƒ์„ ๋งํ•ฉ๋‹ˆ๋‹ค. ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ณด๋‹ค ์ž‘์„ฑ์ด ์–ด๋ ต๊ณ  ์†๋„๊ฐ€ ๋Š๋ฆฝ๋‹ˆ๋‹ค. ์‹คํŒจ ์‹œ์—, ์–ด๋–ค ๋ชจ๋“ˆ์—์„œ ์‹คํŒจํ•œ๊ฑด์ง€ ํ˜น์€ ๋ชจ๋“ˆ ๊ฐ๊ฐ์€ ๋ฌธ์ œ๊ฐ€ ์—†๋”๋ผ๋„ ์–ด๋–ค ์ƒํ˜ธ์ž‘์šฉ์—์„œ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธด ๊ฒƒ์ธ์ง€ ๋“ฑ๋“ฑ ๋‹ค์†Œ ์ •ํ™•ํžˆ ๋ฌธ์ œ ์›์ธ์„ ํŒŒ์•…ํ•˜๊ธฐ๊ฐ€ ์–ด๋ ต๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • E2E ํ…Œ์ŠคํŠธ : ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๋ณด๋‹ค ๋” ํฐ ๊ฐœ๋…์œผ๋กœ, ์œ ์ €์˜ ํ–‰๋™์— ๋”ฐ๋ผ ์ด๋ค„์ง€๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์‹œ์ž‘๊ณผ ๋๊นŒ์ง€์˜ ํ…Œ์ŠคํŠธ์ž…๋‹ˆ๋‹ค.

Cypress ๋‹ค๋ฃจ๊ธฐ

๋จผ์ € Cypress๋ฅผ ์„ค์น˜ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๋ญ๊ฐ€ ๋๋“ , ์ฒ˜์Œ ๋ฐฐ์šธ ๋•Œ๋Š” ๊ผญ๊ผญ๊ผญ ๊ณต์‹๋ฌธ์„œ(cypress)๋ฅผ ๋“ค์–ด๊ฐ€์„œ ์—ด์‹ฌํžˆ getting started๋ฅผ ์ฐพ์•„์„œ ๋ˆŒ๋Ÿฌ๋ณด๋„๋ก ํ•ฉ๋‹ˆ๋‹ค!!

๊ธฐ์กด ํ”„๋กœ์ ํŠธ root ๋””๋ ‰ํ† ๋ฆฌ์—์„œ ์•„๋ž˜์˜ ๋ช…๋ น์–ด๋กœ cypress๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.

# ๊ฐœ๋ฐœ ์˜์กด์„ฑ์œผ๋กœ ์„ค์น˜
npm install cypress --save-dev

# cypress ์‹คํ–‰(2๊ฐ€์ง€ ๋ชจ๋‘ ๊ฐ€๋Šฅ)
npx cypress open
./node_modules/.bin/cypress open

์ดํ›„ cypress ํด๋” -> e2e ํด๋” ๋‚ด๋ถ€์— appName.cy.js์™€ ๊ฐ™์ด appName์ด๋ผ๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ ํŒŒ์ผ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

๊ณต์‹๋ฌธ์„œ๋ฅผ ํ†ตํ•ด ๋” ๋‹ค์–‘ํ•œ ํ•จ์ˆ˜์™€ ์ปค๋งจ๋“œ๊ฐ€ ์žˆ์ง€๋งŒ, ์•„์ฃผ ๊ฐ„๋‹จํ•œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

describe('์–ด๋–ค ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ธ์ง€ ์ ์–ด์ฃผ์„ธ์š”.', () => {
  // ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์ง„์ž…ํ•ฉ๋‹ˆ๋‹ค.
  beforeEach(() => {
    cy.visit('์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ url ์ฃผ์†Œ๋ฅผ ์ ์–ด์ฃผ์„ธ์š”.');
  });

  it('๋ฒ„ํŠผ์„ ํด๋ฆญ ์‹œ, 0์ด ์ž…๋ ฅ๋ฉ๋‹ˆ๋‹ค.', () => {
    cy.get('.button').click();
    cy.get('.answer').invoke('text').should('eq', String(0));
  });
});

์‚ฌ์‹ค ๊ตฌ์ฒด์ ์ธ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์—†์ง€๋งŒ, ๋Œ€๋ถ€๋ถ„์˜ e2e ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋Š” ์œ„์™€ ๊ฐ™์€ ์–‘์‹์„ ๊ฐ–๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

  1. ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์ง„์ž…
  2. ์–ด๋–ค ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ค๋Š” ํ…Œ์ŠคํŠธ์ธ์ง€ ์ •์˜
  3. ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•ด ์–ด๋–ค ์š”์†Œ๋ฅผ ์„ ํƒํ•˜๊ณ  ์–ด๋–ค ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ์ง€ ์ž‘์„ฑ
  4. 3๋ฒˆ์˜ ๊ณผ์ •์„ ํ†ตํ•ด ์–ด๋–ค ์š”์†Œ์˜ ๊ฐ’์ด ์–ด๋–ค ๊ฐ’์„ ๊ฐ€์ง€๋ฉด ๋˜๋Š”์ง€ ๊ฒ€์ฆ

๊ทธ๋ž˜์„œ ๊ตณ์ด Test๋ฅผ ํ•ด์•ผํ•˜๋Š” ์ด์œ ๊ฐ€ ์žˆ๋‚˜?

์ฒ˜์Œ์—” ์ €๋„ ๊ฒฐ๊ตญ์—” ๋˜ ์ฝ”๋“œ๋ฅผ ์งœ๋Š” ์ผ์ธ๋ฐ, ๊ตณ์ด ํ…Œ์ŠคํŠธ๋ฅผ ํ•ด์•ผํ•˜๋Š”๊ฑด๊ฐ€? ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค. ์œ„์˜ ๊ฐ„๋‹จํ•œ ํ…Œ์ŠคํŠธ์•ผ, ์ œ๊ฐ€ ์ง์ ‘ ์œ ์ €์˜ ์ž…์žฅ์ด ๋˜์–ด ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œ์ผœ๋ณด๊ณ  ์ด๊ฒƒ์ €๊ฒƒ ์š”๋ฆฌ์กฐ๋ฆฌ ๋งŒ์ ธ๋ณด๋ฉด ๋ ํ…Œ๋‹ˆ๊นŒ์š”! ํ•˜์ง€๋งŒ, ์šฐ๋ฆฌ๊ฐ€ ์—…๋ฌด๋ฅผ ์ง„ํ–‰ํ•˜๋ฉด์„œ ๊ธฐํš์ž, QA, ์œ ์ € ๋“ฑ๋“ฑ์—๊ฒŒ ๋งค๋ฒˆ ์ˆ˜๋™์œผ๋กœ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋ฌธ์ œ๊ฐ€ ์—†์Œ์„ ๋ณด์—ฌ์ค„ ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค.(๋„ˆ๋ฌด๋‚˜ ๋งŽ์€ ์‹œ๊ฐ„ ์†Œ๋น„). ๊ฐœ๋ฐœ์ž๋ž€ ์ž๊ณ ๋กœ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ณ  ์ž๋™ํ™”๋ฅผ ํ•ด์•ผํ•˜๋Š” ๋ฒ•..! ์ด๋ ‡๊ฒŒ ๋ฒˆ๊ฑฐ๋กœ์šด ๊ณผ์ •์„ ๊ฐ„๋‹จํ•œ ์ฝ”๋“œ ๋ช‡์ค„๋กœ ๋‹จ์‹œ๊ฐ„์— ์—ฌ๋Ÿฌ๋ฒˆ ๋Œ๋ ค๋ณผ ์ˆ˜ ์žˆ๊ณ , ๋ฌด์—‡๋ณด๋‹ค ๊ฐœ๋ฐœ์ž ๋ณธ์ธ๋„ ๋ณธ์ธ์˜ ์ฝ”๋“œ์— ๋Œ€ํ•œ ํ™•์‹ ๊ณผ ์ž์‹ ๊ฐ์„ ์–ป์„ ์ˆ˜ ์žˆ๊ธฐ์— ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.(ํ•„์ˆ˜ ํ•„์ˆ˜) ๋‹จ, ๋ฐฐ๋ณด๋‹ค ๋ฐฐ๊ผฝ์ด ํฌ๋ฉด ์•ˆ๋˜๋“ฏ, ๋˜๋ ค ๊ฐ„๋‹จํ•œ ๊ธฐ๋Šฅ์— ๋Œ€ํ•ด์„œ ํ•˜๋‚˜ํ•˜๋‚˜ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ฒŒ ๋˜๋ฉด ์˜คํžˆ๋ ค ๋” ๋น„ํšจ์œจ์ ์ธ ์ƒํ™ฉ์ด ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•จ์œผ๋กœ์จ ๊ฐ€์žฅ ํฌ๊ฒŒ ํšจ์œจ์„ ์–ป์„ ์ˆ˜ ์žˆ๋Š” ์ ๋‹นํ•จ์„ ๊ฐ€์ง€๋Š” ๊ฒƒ๋„ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ์ข‹์€ ํ…Œ์ŠคํŠธ๋ž€ ๋ญ˜๊นŒ?

  • ์‹คํ–‰ ์†๋„๊ฐ€ ๋น ๋ฅผ ๊ฒƒ
  • ๋ณธ ์ฝ”๋“œ๊ฐ€ ๋ฆฌํŒฉํ† ๋ง๋˜์–ด๋„ ํ…Œ์ŠคํŠธ๋Š” ๊ทธ๋Œ€๋กœ ์ž˜ ์ž‘๋™๋  ๊ฒƒ
  • ๋””๋ฒ„๊น…์ด ๊ฐ€๋Šฅํ•  ๊ฒƒ
  • ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ๊ฐ€ ํ•ญ์ƒ ์ผ์ •ํ•˜๊ณ  ์•ˆ์ •์ ์ผ ๊ฒƒ
  • ํ…Œ์ŠคํŠธ์˜ ์˜๋„(์‚ฌ๋žŒ์ด ๋ณด๋Š” ๊ฒƒ)๊ฐ€ ๋ช…ํ™•ํ•  ๊ฒƒ

Reference