[DevCamp] ๐Ÿงช E2E ํ…Œ์ŠคํŠธ ์ž๋™ํ™”๋กœ ์‹ ๋ขฐ์„ฑ ๋†’์€ ํ”„๋ก ํŠธ์—”๋“œ ๋งŒ๋“ค๊ธฐ

๋™๊ฑดยท2025๋…„ 6์›” 3์ผ

DevCamp

๋ชฉ๋ก ๋ณด๊ธฐ
78/85

๐Ÿงช E2E ํ…Œ์ŠคํŠธ ์ž๋™ํ™”๋กœ ์‹ ๋ขฐ์„ฑ ๋†’์€ ํ”„๋ก ํŠธ์—”๋“œ ๋งŒ๋“ค๊ธฐ

ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์—์„œ๋Š” UI๊ฐ€ ์‚ฌ์šฉ์ž์™€ ์ง์ ‘ ๋งž๋‹ฟ์•„ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—,
์ „์ฒด์ ์ธ ์‚ฌ์šฉ์ž ํ๋ฆ„์ด ์˜๋„๋Œ€๋กœ ๋™์ž‘ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ด ๋งค์šฐ ์ค‘์š”ํ•˜๋‹ค.

์ด๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋ฐ”๋กœ E2E(End-to-End) ํ…Œ์ŠคํŠธ์ด๋ฉฐ,
์ด๋ฅผ ์ž๋™ํ™”ํ•จ์œผ๋กœ์จ ๊ฐœ๋ฐœ ํšจ์œจ๊ณผ ์„œ๋น„์Šค ์‹ ๋ขฐ์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ๋‹ค.


๐Ÿ“Œ E2E ํ…Œ์ŠคํŠธ๋ž€?

์‚ฌ์šฉ์ž๊ฐ€ ์‹ค์ œ๋กœ ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํ๋ฆ„ ์ „์ฒด๋ฅผ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ํ•˜๋Š” ํ…Œ์ŠคํŠธ

๋‹จ์œ„ ํ…Œ์ŠคํŠธ(unit test), ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ(integration test)์™€ ๋‹ฌ๋ฆฌ, UI๋ฅผ ํ†ตํ•ด ์‹ค์ œ ๋™์ž‘์„ ๊ฒ€์ฆํ•œ๋‹ค. ํ”„๋ก ํŠธ์™€ ๋ฐฑ์—”๋“œ, DB๊ฐ€ ํ•จ๊ป˜ ์—ฐ๋™๋œ ์ƒํƒœ์—์„œ ํ…Œ์ŠคํŠธ๊ฐ€ ์ˆ˜ํ–‰๋œ๋‹ค.


๐Ÿงฐ ๋Œ€ํ‘œ์ ์ธ E2E ํ…Œ์ŠคํŠธ ๋„๊ตฌ

๋„๊ตฌํŠน์ง•
Cypress์ง๊ด€์ ์ธ API์™€ ๋น ๋ฅธ ์‹คํ–‰ ์†๋„
Playwright๋‹ค์–‘ํ•œ ๋ธŒ๋ผ์šฐ์ € ์ง€์› (Chrome, Firefox, WebKit)
PuppeteerHeadless Chrome ๊ธฐ๋ฐ˜, Google์ด ๊ฐœ๋ฐœ

๐Ÿš€ Cypress๋ฅผ ํ™œ์šฉํ•œ E2E ํ…Œ์ŠคํŠธ ์ž๋™ํ™” ์˜ˆ์‹œ

1. ์„ค์น˜

npm install cypress --save-dev

2. ํ…Œ์ŠคํŠธ ์Šคํฌ๋ฆฝํŠธ ์˜ˆ์‹œ (cypress/e2e/login.cy.ts)

describe('๋กœ๊ทธ์ธ ํ…Œ์ŠคํŠธ', () => {
  it('๋กœ๊ทธ์ธ ์„ฑ๊ณต ์‹œ ๋ฉ”์ธ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•œ๋‹ค', () => {
    cy.visit('/login');
    cy.get('input[name="email"]').type('user@example.com');
    cy.get('input[name="password"]').type('123456');
    cy.get('button[type="submit"]').click();
    cy.url().should('include', '/main');
  });
});

3. ์‹คํ–‰

npx cypress open  # UI ์‹คํ–‰
npx cypress run   # CLI ์‹คํ–‰

โš™๏ธ ์ž๋™ํ™” ์ „๋žต

  • CI ํ™˜๊ฒฝ(GitHub Actions ๋“ฑ)์— Cypress๋ฅผ ํ†ตํ•ฉํ•ด PR๋งˆ๋‹ค ํ…Œ์ŠคํŠธ ์ž๋™ ์ˆ˜ํ–‰
  • ํ…Œ์ŠคํŠธ ์‹คํŒจ ์‹œ Slack/Discord ์•Œ๋ฆผ ์—ฐ๋™
  • ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ„๋„๋กœ ์ค€๋น„ํ•ด ํ…Œ์ŠคํŠธ์˜ ๋…๋ฆฝ์„ฑ ํ™•๋ณด

๐Ÿ“Œ ์ข‹์€ E2E ํ…Œ์ŠคํŠธ ์ž‘์„ฑ ํŒ

  • ํ…Œ์ŠคํŠธ ๋ชฉ์ ์ด ๋ช…ํ™•ํ•œ ์‹œ๋‚˜๋ฆฌ์˜ค ์ž‘์„ฑ
  • id, data-testid๋กœ ์…€๋ ‰ํ„ฐ ๋ช…์‹œ์  ์ง€์ • (UI ๋ณ€๊ฒฝ์— ์˜ํ–ฅ ์ ๊ฒŒ ๋ฐ›๊ธฐ ์œ„ํ•จ)
  • ๊ณตํ†ต ๋กœ์ง์€ ์ปค๋งจ๋“œ ๋˜๋Š” ํ•จ์ˆ˜๋กœ ์ถ”์ถœํ•˜์—ฌ ์žฌ์‚ฌ์šฉ์„ฑ ํ™•๋ณด
  • ์†๋„๋ณด๋‹ค ์‹ ๋ขฐ์„ฑ ์šฐ์„ : ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” cy.wait() ๋Œ€์‹  ๋ช…ํ™•ํ•œ ์กฐ๊ฑด ์‚ฌ์šฉ

๐Ÿง  TIL

  • ์„œ๋น„์Šค๊ฐ€ ์ปค์งˆ์ˆ˜๋ก ์ˆ˜๋™ ํ…Œ์ŠคํŠธ์˜ ํ•œ๊ณ„๋Š” ๋ถ„๋ช…ํ•ด์ง€๊ณ , ์ž๋™ํ™”๋Š” ํ•„์ˆ˜๋กœ ์ž๋ฆฌ์žก๋Š”๋‹ค.
  • E2E ํ…Œ์ŠคํŠธ๋Š” ๋‹จ์ˆœ ๊ฒ€์ฆ์„ ๋„˜์–ด ๊ฐœ๋ฐœ์ž์˜ ์ž์‹ ๊ฐ์„ ๋ณด์žฅํ•ด์ฃผ๋Š” ์•ˆ์ „๋ง์ด๋‹ค.
  • ์‹œ๊ฐ„์„ ๋“ค์—ฌ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์ด ๊ฒฐ๊ตญ์€ ๋น ๋ฅธ ๋ฐฐํฌ์™€ ์•ˆ์ •์„ฑ์„ ๋งŒ๋“ ๋‹ค.
profile
๋ฐฐ๊ณ ํ”ˆ ๊ฐœ๋ฐœ์ž

0๊ฐœ์˜ ๋Œ“๊ธ€