mason
mason-log.

GitHub 로그인 중

E2E 테스트 (Playwright).
mason

masonfe-hyunsu

🎭 1. 개요 : E2E 테스트란 무엇인가.

E2E 테스트 개요
  • 사용자가 서비스를 이용하는 흐름을 처음부터 끝까지 검사하는 방식을 E2E(End-to-End) 테스트라고 한다.

  • 함수 하나하나는 정상이어도, 그것들이 연결된 전체 흐름은 실제 브라우저에서 확인해야 알 수 있다.

  • 단위 테스트가 아무리 많아도 실제 서비스에서는 다른 종류의 문제가 생긴다. 링크가 엉뚱한 곳으로 가거나, 페이지 이동이 중간에 막히는 문제다.

  • 이 포스팅에서는 E2E 테스트가 무엇을 검사하는지, Playwright로 어떻게 작성하는지, 어떻게 안정적으로 유지하는지 정리해 본다.

E2E 테스트는 사용자가 실제로 이용하는 경로가 끝까지 동작하는지 확인한다.


🧪 2. 단위 테스트와 무엇이 다른가.

단위 테스트와 E2E 테스트는 확인하는 범위가 다르다.

  • 단위 테스트

    • 함수나 작은 로직을 따로 검사한다.

    • 실행이 빠르고 문제의 원인을 찾기 쉽다.

    • 예: 날짜 변환 함수가 원하는 문자열을 반환하는지 확인한다.

  • E2E 테스트

    • 실제 브라우저에서 여러 기능이 연결된 흐름을 검사한다.

    • 페이지, 라우팅, 버튼, 데이터 표시가 함께 동작하는지 알 수 있다.

    • 예: 목록에서 항목을 누른 뒤 상세 페이지가 열리는지 확인한다.

둘 중 하나를 고르는 관계는 아니다. 작은 로직은 단위 테스트로 빠르게 확인하고, 중요한 사용자 흐름은 E2E 테스트로 한 번 더 확인한다.

단위 테스트와 E2E 테스트가 확인하는 범위 비교

🎯 3. 도구는 왜 Playwright인가.

E2E 도구로는 Cypress와 Playwright가 자주 비교된다. 둘 다 성숙한 도구지만, 새로 시작한다면 Playwright를 권하고 싶다.

  • 멀티 브라우저: Chromium, Firefox, WebKit을 한 API로 다룬다.

  • 자동 대기: 버튼이나 링크가 준비될 때까지 자동으로 기다린다.

  • 트레이스 뷰어: 실패한 테스트의 실행 과정을 타임라인으로 되감아 볼 수 있다.

  • CI 친화: headless 실행과 병렬 실행이 기본에 가깝다.

처음부터 모든 브라우저를 검사할 필요는 없다. Chromium 하나로 시작해서 필요해지면 늘리는 편이 관리하기 쉽다.


📦 4. 설치와 설정.

테스트 패키지를 개발 의존성으로 설치하고, 브라우저를 별도로 받는다.

npm install -D @playwright/test
npx playwright install chromium

설정과 테스트 파일은 한 폴더에 모아 두면 프로젝트 루트가 지저분해지지 않는다.

e2e/
├── playwright.config.ts
└── home.spec.ts

설정 파일에서는 테스트 위치, 실행할 브라우저, 개발 서버 주소를 정한다.

// e2e/playwright.config.ts
import { defineConfig, devices } from '@playwright/test';

const BASE_URL = 'http://localhost:3000';

export default defineConfig({
  testDir: '.',
  testMatch: '**/*.spec.ts',
  use: {
    baseURL: BASE_URL,
    trace: 'on-first-retry',
  },
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
  ],
  webServer: {
    command: 'npm run dev',
    url: BASE_URL,
    reuseExistingServer: !process.env.CI,
  },
});

처음 보면 옵션이 많아 보이지만 역할은 단순하다.

  • baseURL: 테스트에서 /login처럼 경로만 적을 수 있게 기준 주소를 정한다.

  • webServer: 테스트 전에 개발 서버를 자동으로 실행한다. 서버를 따로 켜 둘 필요가 없다.

  • reuseExistingServer: 이미 개발 서버가 실행 중이면 그대로 사용한다.

  • trace: 재시도할 때 브라우저 동작 기록을 남긴다.

package.json에는 실행 명령만 추가한다.

{
  "scripts": {
    "test:e2e": "playwright test --config e2e/playwright.config.ts"
  }
}

✍️ 5. 첫 번째 사용자 흐름 작성하기.

첫 테스트는 서비스에서 가장 자주 지나는 길 하나를 고른다. 목록 페이지에서 상세 페이지로 이동하는 흐름이 좋은 예다.

// e2e/home.spec.ts
import { test, expect } from '@playwright/test';

test('목록에서 항목을 누르면 상세 페이지로 이동한다', async ({ page }) => {
  await page.goto('/');

  const firstItem = page.locator('a[href^="/detail/"]').first();
  await expect(firstItem).toBeVisible();

  await firstItem.click();
  await expect(page).toHaveURL(/\/detail\//);
});

코드를 순서대로 읽으면 실제 사용자의 행동과 비슷하다.

  1. page.goto('/')로 홈을 연다.

  2. 첫 번째 항목 링크를 찾는다.

  3. 링크가 화면에 보이는지 확인한다.

  4. 링크를 누른다.

  5. 주소가 상세 페이지 경로로 바뀌었는지 확인한다.

테스트는 다음 명령으로 실행한다.

npm run test:e2e
E2E 실행 흐름 : 서버 실행, 사용자 흐름 검사, 결과 확인
  • Playwright가 개발 서버를 준비한다.

  • Chromium이 페이지를 열고 지정한 동작을 수행한다.

  • 예상한 결과와 같으면 테스트가 통과한다.

  • 실패하면 어느 단계에서 문제가 생겼는지 결과와 트레이스로 확인한다.


🔁 6. 안정적인 테스트로 유지하기.

E2E 테스트는 화면과 실행 환경의 영향을 받는다. 따라서 테스트를 많이 만드는 것보다 중요한 경로를 안정적으로 검사하는 편이 좋다.

  • 사용자가 이해할 수 있는 이름으로 요소를 찾는다.

    • getByRole('button', { name: '로그인' })

    • getByLabel('이메일')

  • 꼭 필요한 경우에만 data-testid를 사용한다.

  • setTimeout이나 고정된 대기 시간을 넣지 않는다.

  • 외부 데이터가 매번 달라지는 테스트는 피한다.

Playwright의 expect는 조건이 만족될 때까지 일정 시간 기다린다.

await expect(page.getByText('저장 완료')).toBeVisible();

따라서 화면이 뜰 때까지 임의로 몇 초를 기다리는 코드보다, 확인하려는 상태를 직접 적는 편이 명확하다.

안정적인 요소 선택 방법과 Playwright 자동 대기

테스트가 가끔 실패한다면 대기 방식, 요소를 찾는 방법, 테스트 데이터 순서로 확인한다.


🤖 7. CI에서는 어떻게 실행할까.

CI(자동 검사 환경)에서는 패키지를 설치한 뒤 Chromium과 E2E 테스트를 실행하면 된다.

- name: Install Playwright browser
  run: npx playwright install --with-deps chromium

- name: Run E2E
  run: npm run test:e2e
  • --with-deps는 CI의 리눅스 환경에 필요한 시스템 패키지도 함께 설치한다.

  • CI에서는 reuseExistingServer가 꺼지므로 webServer가 매번 새 서버를 띄운다.

  • 테스트가 실패하면 리포트와 트레이스를 아티팩트로 남겨 원인을 확인할 수 있다.


🔺 8. 테스트 피라미드에서의 위치.

E2E 테스트는 강력하지만 느리고 깨지기 쉽다. 그래서 많이 두면 안 된다.

        E2E (적게)
      통합 / 컴포넌트
   단위 (Vitest/Jest)  ← 많이
  • 아래(단위)는 많고 빠르게, 위(E2E)로 갈수록 적고 굵게 가져간다.

  • 유틸이나 순수 로직까지 E2E로 올리면 스위트가 무거워지고 자주 깨진다.

  • E2E는 로그인, 결제, 주요 페이지 이동처럼 실패했을 때 영향이 큰 흐름부터 추가한다.

Playwright UI에서는 테스트 목록, 실행 단계, 브라우저 화면을 한곳에서 확인할 수 있다. 아래는 npm run test:e2e:ui로 실행 결과를 확인한 화면이다.

Playwright UI에서 E2E 테스트 실행 결과를 확인한 화면

📋 9. 정리.

  • E2E 테스트는 실제 브라우저에서 사용자 흐름이 끝까지 동작하는지 확인한다.

  • 단위 테스트와 역할이 다르므로 대체 관계가 아니라 보완 관계다.

  • Playwright는 자동 대기, 트레이스, 멀티 브라우저 지원으로 시작하기 좋다.

  • 설정과 테스트를 한 폴더에 모으면 프로젝트 구조를 단순하게 유지할 수 있다.

  • 테스트 수를 늘리는 것보다 중요한 흐름을 안정적으로 유지하는 데 집중한다.

E2E 테스트를 별도의 거대한 작업으로 만들 필요는 없다. 사용자가 자주 지나는 경로 하나를 골라 실제 브라우저로 확인하는 것부터 시작하면 된다. 이후에는 실패했을 때 영향이 큰 흐름을 중심으로 조금씩 넓혀 가면 충분하다.


🔗 10. 참고 자료.

이전 글
masoneffect NPM Update.(ver2)

댓글

불러오는 중...
목록으로