튜토리얼

Playwright E2E 테스트 자동화 완벽 가이드: CI/CD 연동부터 리포팅까지

강코의 코딩 일기 2026. 5. 14. 13:24
반응형

웹 애플리케이션의 품질을 높이고 개발 효율을 극대화하고 싶으신가요? Playwright를 활용한 E2E 테스트 자동화 시스템을 구축하고 CI/CD 파이프라인에 연동하여 안정적인 배포와 상세한 리포팅까지 경험해보세요.

개발한 웹 애플리케이션이 실제 환경에서 제대로 작동하는지 확신하기 어려웠던 경험이 있으신가요? 새로운 기능을 추가할 때마다 기존 기능이 오작동할까 불안하고, 배포 직전에 수동으로 모든 기능을 일일이 확인하느라 시간을 허비하고 계시지는 않으신가요?

이러한 문제들은 웹 애플리케이션 개발 과정에서 흔히 겪는 난관입니다. 특히 복잡한 웹 서비스의 경우, 수동 테스트만으로는 모든 시나리오를 커버하기 어렵고, 사람의 실수로 인해 중요한 버그를 놓칠 위험이 항상 존재합니다. 이는 곧 서비스 품질 저하와 개발 생산성 하락으로 이어지기 마련입니다.

다행히도 이러한 문제들을 효과적으로 해결할 수 있는 방법이 있습니다. 바로 E2E(End-to-End) 테스트 자동화입니다. 사용자 관점에서 실제 브라우저를 통해 애플리케이션의 모든 흐름을 자동으로 검증함으로써, 개발 과정에서의 불안감을 해소하고 안정적인 서비스 운영을 가능하게 합니다. 그리고 그 중심에는 Playwright라는 강력한 도구가 있습니다.

본 가이드에서는 Playwright를 활용하여 웹 애플리케이션의 E2E 테스트를 자동화하는 방법을 소개합니다. 단순히 테스트 코드를 작성하는 것을 넘어, CI/CD 파이프라인에 연동하여 개발 워크플로우를 혁신하고, 상세한 리포팅을 통해 문제점을 신속하게 파악하는 방법까지, 실용적인 관점에서 모든 과정을 단계별로 안내해 드리겠습니다.

📑 목차

웹 애플리케이션 테스트, 왜 E2E 자동화가 필수일까요?

웹 애플리케이션 개발에 있어 테스트는 선택이 아닌 필수입니다. 하지만 어떤 종류의 테스트를, 얼마나 자동화해야 하는지에 대한 고민은 개발팀마다 다를 수 있습니다. 특히 E2E 테스트는 사용자 경험의 핵심을 검증하는 과정으로, 서비스의 안정성과 신뢰도를 보장하는 데 결정적인 역할을 합니다.

수동 테스트의 한계와 자동화의 필요성

과거에는 QA 엔지니어나 개발자가 직접 브라우저를 열고 웹사이트를 클릭하며 기능을 검증하는 수동 테스트가 주를 이루었습니다. 그러나 이러한 방식은 여러 가지 심각한 한계를 가지고 있습니다.

  • 시간과 비용 소모: 새로운 기능이 추가되거나 기존 코드가 변경될 때마다 전체 기능을 수동으로 다시 테스트하는 것은 막대한 시간과 인력을 요구합니다. 서비스 규모가 커질수록 이 부담은 기하급수적으로 증가합니다.
  • 휴먼 에러 가능성: 사람은 반복적인 작업에 지치기 마련이며, 이는 곧 실수로 이어질 수 있습니다. 중요한 시나리오를 놓치거나 잘못된 판단을 내릴 가능성이 항상 존재합니다.
  • 재현성 부족: 특정 환경에서만 발생하는 버그를 수동으로 재현하기 어렵고, 테스트 결과의 일관성을 유지하기 힘듭니다.
  • 개발 속도 저해: 테스트에 많은 시간이 소요되면, 개발 주기가 길어지고 새로운 기능 배포가 늦어져 시장 경쟁력을 잃을 수 있습니다.

이러한 문제들을 해결하기 위해 E2E 테스트 자동화가 필수적입니다. 자동화된 E2E 테스트는 실제 사용자가 겪을 수 있는 모든 시나리오를 프로그램적으로 실행하고 검증합니다. 이를 통해 개발팀은 다음과 같은 이점을 얻을 수 있습니다.

  • 높은 신뢰도: 반복적이고 일관된 테스트 실행으로 버그를 조기에 발견하고 재발을 방지합니다.
  • 개발 생산성 향상: 수동 테스트에 드는 시간을 절약하여 개발자가 핵심 기능 개발에 집중할 수 있도록 돕습니다.
  • 빠른 피드백: CI/CD 파이프라인과 연동하여 코드 변경 시 즉각적인 테스트 결과를 받아볼 수 있습니다.
  • 비용 절감: 장기적으로 테스트 및 QA에 필요한 인력과 시간을 크게 줄일 수 있습니다.

결론적으로, E2E 테스트 자동화는 웹 애플리케이션의 품질을 향상시키고 개발 효율성을 극대화하기 위한 핵심 전략입니다.

Playwright, 왜 E2E 테스트의 강력한 동반자인가?

E2E 테스트 자동화 도구는 다양하게 존재하지만, 최근 몇 년간 개발자들 사이에서 Playwright가 빠르게 각광받고 있습니다. 그렇다면 Playwright가 다른 도구들과 차별화되는 강점은 무엇일까요?

경쟁 도구들과의 비교

Playwright의 장점을 명확히 이해하기 위해, 기존의 대표적인 E2E 테스트 도구인 Selenium 및 Cypress와 비교해보겠습니다.

특징 Playwright Cypress Selenium WebDriver
지원 브라우저 Chromium, Firefox, WebKit (Safari), 모바일 에뮬레이션 Chrome, Firefox, Edge, Electron 모든 주요 브라우저 (드라이버 필요)
지원 언어 TypeScript, JavaScript, Python, Java, .NET JavaScript, TypeScript 다양한 언어 (Java, Python, C#, Ruby, JavaScript 등)
병렬 실행 기본 지원 (워커 프로세스 기반) 유료 서비스 또는 플러그인 필요 WebDriver Grid를 통해 지원
자동 대기 (Auto-waiting) 매우 강력하고 지능적인 자동 대기 기능 내장 내장 (일부 제한 있음) 명시적/암시적 대기 필요
테스트 실행 환경 실제 브라우저 (Headful/Headless) 브라우저 내에서 실행 실제 브라우저 (Headful/Headless)
CI/CD 통합 매우 용이 (경량, 컨테이너 친화적) 용이 (일부 설정 필요) 드라이버 관리 및 환경 설정 필요

Playwright의 주요 강점

위 표에서 보듯이, Playwright는 여러 면에서 뛰어난 성능을 자랑합니다.

  • 크로스 브라우저 지원: Chromium (Google Chrome, Microsoft Edge), Firefox, WebKit (Apple Safari) 등 모든 주요 브라우저를 단일 API로 지원합니다. 이는 테스트 코드의 재사용성을 높이고, 다양한 환경에서의 일관된 동작을 보장합니다.
  • 강력한 자동 대기 (Auto-waiting): Playwright는 요소가 나타나고, 활성화되고, 애니메이션이 끝나는 등 다양한 상태 변화를 자동으로 감지하고 기다립니다. 이 기능 덕분에 개발자는 `sleep()`과 같은 명시적인 대기 코드를 최소화하여 불안정한 테스트(Flaky Test) 발생 가능성을 크게 줄일 수 있습니다.
  • 병렬 실행: 기본적으로 여러 테스트를 동시에 실행할 수 있는 기능을 제공합니다. 이는 수백 개의 테스트 케이스를 가진 대규모 프로젝트에서 테스트 시간을 획기적으로 단축시켜 줍니다. 예를 들어, 100개의 테스트를 4개의 워커로 병렬 실행하면 이론적으로 테스트 시간을 1/4로 줄일 수 있습니다.
  • 다양한 언어 지원: JavaScript/TypeScript 외에도 Python, Java, .NET 등 다양한 프로그래밍 언어를 지원하여 팀의 기술 스택에 맞춰 유연하게 선택할 수 있습니다.
  • 리치 기능 세트: 파일 업로드/다운로드, 네트워크 요청 가로채기, 비디오 녹화, 스크린샷 캡처, 모바일 에뮬레이션 등 E2E 테스트에 필요한 거의 모든 기능을 내장하고 있습니다. 특히 코드 생성기(Codegen) 기능을 통해 실제 브라우저에서 수행하는 동작을 자동으로 테스트 코드로 변환해주는 기능은 테스트 코드 작성 시간을 대폭 단축시켜 줍니다.
  • CI/CD 친화적: 경량이며 설치가 간단하여 CI/CD 환경에 통합하기 매우 용이합니다. Docker 컨테이너 등 다양한 환경에서 안정적으로 작동합니다.

이러한 강점들 덕분에 Playwright는 웹 애플리케이션의 복잡한 E2E 테스트를 안정적이고 효율적으로 자동화하는 데 최적의 선택이 될 수 있습니다.

Playwright E2E 테스트 환경 구축 및 기본 작성 가이드

이제 Playwright를 사용하여 실제 테스트 환경을 구축하고 기본적인 테스트 코드를 작성하는 방법을 알아보겠습니다. 이 섹션에서는 Node.js 환경을 기준으로 설명합니다.

Playwright 설치 및 초기 설정

가장 먼저 Node.js가 설치되어 있어야 합니다. 터미널을 열고 새 프로젝트 디렉토리를 생성한 후, Playwright를 설치합니다.


# 새 프로젝트 디렉토리 생성 및 이동
mkdir playwright-e2e-tutorial
cd playwright-e2e-tutorial

# npm 프로젝트 초기화
npm init -y

# Playwright 설치 (이때 기본 브라우저 바이너리도 함께 설치됩니다)
npm init playwright@latest

npm init playwright@latest 명령을 실행하면 Playwright가 필요한 패키지와 함께 Chromium, Firefox, WebKit 브라우저 바이너리까지 자동으로 설치해줍니다. 설치 과정에서 몇 가지 질문이 나올 수 있습니다. 예를 들어, TypeScript를 사용할지, 테스트 파일을 어느 디렉토리에 저장할지 등을 묻습니다. 기본 설정을 따르는 것이 일반적입니다.


# .github/workflows/playwright.yml 파일 생성 여부? (GitHub Actions 연동 시 Y)
# TypeScript 사용 여부? (Y)
# 테스트 파일 저장 디렉토리? (tests)
# end-to-end 테스트를 위한 브라우저 설치? (Y)

설치가 완료되면 package.json 파일에 Playwright 관련 스크립트가 추가된 것을 확인할 수 있습니다. 기본적으로 test 스크립트가 생성됩니다.


{
  "name": "playwright-e2e-tutorial",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "playwright test",
    "test:headed": "playwright test --headed",
    "test:debug": "playwright test --debug",
    "playwright:codegen": "playwright codegen"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@playwright/test": "^1.x.x",
    "@types/node": "^20.x.x"
  }
}

이제 npm test 명령으로 기본 예제 테스트를 실행할 수 있습니다.


npm test

테스트가 성공적으로 실행되면, HTML 리포터가 자동으로 생성되고 브라우저로 열립니다. 이는 Playwright의 강력한 기능 중 하나로, 테스트 결과를 시각적으로 쉽게 파악할 수 있도록 돕습니다.

기본 테스트 시나리오 작성

Playwright는 @playwright/test 패키지를 통해 테스트 프레임워크를 제공합니다. 기본적인 테스트 구조는 test() 함수와 expect() 함수를 사용합니다. 예를 들어, 특정 웹사이트에 접속하여 제목을 확인하고, 로그인 폼에 값을 입력한 후 버튼을 클릭하는 시나리오를 작성해 보겠습니다. (테스트할 가상의 웹사이트 URL을 사용합니다.)


// tests/example.spec.ts (TypeScript 기준)
import { test, expect } from '@playwright/test';

test.describe('Playwright 데모 웹사이트 테스트', () => {

  // 각 테스트 실행 전에 특정 URL로 이동
  test.beforeEach(async ({ page }) => {
    await page.goto('https://www.example.com/login'); // 테스트할 웹사이트 URL로 변경
  });

  test('로그인 페이지가 올바르게 로드되어야 한다', async ({ page }) => {
    // 페이지 제목 확인
    await expect(page).toHaveTitle(/로그인|Login/);
    // 특정 텍스트가 페이지에 있는지 확인
    await expect(page.locator('h1')).toHaveText('로그인');
  });

  test('유효한 자격 증명으로 로그인에 성공해야 한다', async ({ page }) => {
    // 사용자 이름 입력 필드 찾기 및 값 입력
    await page.fill('input[name="username"]', 'testuser');
    // 비밀번호 입력 필드 찾기 및 값 입력
    await page.fill('input[name="password"]', 'password123');
    // 로그인 버튼 클릭
    await page.click('button[type="submit"]');

    // 로그인 성공 후 리다이렉트된 페이지의 URL 확인
    await expect(page).toHaveURL('https://www.example.com/dashboard'); // 성공 후 URL로 변경
    // 성공 메시지 또는 대시보드 특정 요소 확인
    await expect(page.locator('.welcome-message')).toHaveText(/환영합니다|Welcome, testuser/);
  });

  test('잘못된 비밀번호로 로그인 실패 시 에러 메시지를 보여줘야 한다', async ({ page }) => {
    await page.fill('input[name="username"]', 'testuser');
    await page.fill('input[name="password"]', 'wrongpassword');
    await page.click('button[type="submit"]');

    // 에러 메시지 확인
    await expect(page.locator('.error-message')).toHaveText('잘못된 사용자 이름 또는 비밀번호입니다.');
    // 여전히 로그인 페이지에 머물러 있는지 확인
    await expect(page).toHaveURL('https://www.example.com/login');
  });
});

위 코드에서 page 객체는 현재 브라우저 페이지를 나타내며, 이를 통해 웹 페이지와 상호작용합니다. fill(), click(), goto() 등 직관적인 API를 사용하여 실제 사용자처럼 웹 페이지를 조작할 수 있습니다. expect() 함수는 검증 로직을 담당하며, 다양한 어설션(assertion)을 제공합니다. 예를 들어, toHaveTitle()은 페이지 제목을, toHaveURL()은 URL을, toHaveText()는 특정 요소의 텍스트 내용을 검증합니다.

요소 선택 전략

Playwright에서 가장 중요한 부분 중 하나는 정확하고 안정적으로 요소를 선택하는 것입니다. Playwright는 다양한 선택자(selector) 전략을 지원하며, 몇 가지 팁을 활용하면 더욱 견고한 테스트를 작성할 수 있습니다.

  • 텍스트 기반 선택자: page.getByText('로그인')와 같이 사용자에게 보이는 텍스트를 기반으로 요소를 선택합니다. 이는 가장 사용자 친화적이고 직관적인 방법입니다.
  • 역할 기반 선택자: page.getByRole('button', { name: '로그인' })와 같이 요소의 접근성 역할(ARIA role)과 이름을 사용하여 선택합니다. 이는 접근성을 고려한 테스트 작성에 유리합니다.
  • Placeholder 기반 선택자: page.getByPlaceholder('아이디를 입력하세요')와 같이 입력 필드의 placeholder 텍스트를 사용합니다.
  • Label 기반 선택자: page.getByLabel('사용자 이름')와 같이 <label> 태그의 텍스트를 사용하여 관련 입력 필드를 선택합니다.
  • Test ID 기반 선택자: 개발자가 테스트를 위해 data-testid="username-input"과 같은 커스텀 속성(Custom Attribute)을 부여하고 page.getByTestId('username-input')으로 선택하는 방법입니다. 이는 CSS 클래스나 ID가 변경되어도 테스트가 깨지지 않도록 하는 가장 안정적인 방법으로 권장됩니다.
  • CSS 선택자: page.locator('input#username') 또는 page.locator('.login-form button.submit')와 같이 일반적인 CSS 선택자를 사용할 수 있습니다. 그러나 CSS 선택자는 UI 변경에 취약할 수 있으므로, 가능한 한 다른 선택자를 우선적으로 고려하는 것이 좋습니다.

안정적인 E2E 테스트를 위해서는 개발 초기부터 Test ID를 부여하는 규칙을 정하고 이를 적극적으로 활용하는 것이 매우 중요합니다. 이는 테스트 코드의 가독성과 유지보수성을 크게 향상시킵니다.

CI/CD 파이프라인에 Playwright 테스트 연동하기

E2E 테스트의 진정한 가치는 개발 워크플로우에 통합될 때 발휘됩니다. CI/CD(지속적 통합/지속적 배포) 파이프라인에 Playwright 테스트를 연동하면, 코드 변경이 발생할 때마다 자동으로 테스트를 실행하고 결과를 피드백받아 안정적인 배포를 보장할 수 있습니다.

CI/CD의 중요성

CI/CD는 개발팀이 소프트웨어를 더 빠르고 안정적으로 배포할 수 있도록 돕는 일련의 자동화된 프로세스입니다. CI(Continuous Integration)는 개발자가 코드 변경 사항을 중앙 리포지토리에 자주 병합하도록 장려하며, 이때마다 자동화된 빌드 및 테스트가 실행됩니다. CD(Continuous Delivery/Deployment)는 이러한 변경 사항을 테스트 환경이나 실제 운영 환경까지 자동으로 배포하는 것을 의미합니다.

E2E 테스트를 CI/CD에 통합함으로써 다음과 같은 이점을 얻을 수 있습니다.

  • 조기 버그 발견: 코드 변경 직후 테스트가 실행되므로, 버그가 개발 프로세스 초기에 발견되어 수정 비용을 절감합니다.
  • 지속적인 품질 보증: 모든 코드 변경에 대해 일관된 품질 검증 프로세스를 적용하여 서비스 품질을 유지합니다.
  • 배포 자신감 증가: 자동화된 테스트가 통과했다는 것은 새로운 버전이 안정적으로 작동할 가능성이 높다는 것을 의미하므로, 배포에 대한 확신을 가질 수 있습니다.
  • 개발팀의 신뢰도 향상: 자동화된 시스템이 반복적인 작업을 처리하므로, 개발팀은 더 중요한 문제 해결과 기능 개발에 집중할 수 있습니다.

CI/CD 환경에서 Playwright 실행 전략

대부분의 CI/CD 환경은 리눅스 기반의 컨테이너(예: Docker)에서 실행됩니다. Playwright는 Headless 모드(UI 없이 백그라운드에서 실행)를 기본적으로 지원하므로, CI/CD 환경에서 효율적으로 실행할 수 있습니다.

CI/CD 파이프라인에 Playwright를 연동하는 일반적인 단계는 다음과 같습니다.

  1. Playwright 설치: CI/CD 환경에 Node.js와 npm(또는 yarn)이 설치되어 있는지 확인하고, 프로젝트 의존성과 Playwright 브라우저 바이너리를 설치합니다.
  2. 테스트 실행: playwright test 명령을 사용하여 테스트를 실행합니다. 이때 --headless 옵션은 기본값이므로 명시적으로 지정할 필요는 없지만, 특정 경우(예: 디버깅)에는 --headed 옵션을 사용할 수 있습니다.
  3. 결과 리포팅: 테스트 실행 후 생성된 리포트를 아티팩트(artifact)로 저장하여 개발팀이 결과를 확인할 수 있도록 합니다.

GitHub Actions 연동 예시

GitHub Actions는 GitHub 저장소에서 직접 CI/CD 파이프라인을 구축할 수 있도록 돕는 강력한 도구입니다. 다음은 GitHub Actions를 사용하여 Playwright 테스트를 실행하는 워크플로우 파일의 예시입니다. (.github/workflows/playwright.yml)


name: Playwright E2E Tests

on:
  push:
    branches: [ main, develop ] # main 또는 develop 브랜치에 푸시될 때 실행
  pull_request:
    branches: [ main, develop ] # main 또는 develop 브랜치로 풀 리퀘스트 생성/업데이트 시 실행

jobs:
  test:
    timeout-minutes: 60 # 최대 60분 동안 실행
    runs-on: ubuntu-latest # Ubuntu 최신 버전에서 실행

    steps:
    - uses: actions/checkout@v4 # 저장소 코드 체크아웃
    - uses: actions/setup-node@v4
      with:
        node-version: 20 # Node.js 20 버전 사용

    - name: Install dependencies # 프로젝트 의존성 설치
      run: npm ci

    - name: Install Playwright browsers # Playwright 브라우저 설치
      run: npx playwright install --with-deps

    - name: Run Playwright tests # Playwright 테스트 실행
      run: npx playwright test

    - uses: actions/upload-artifact@v4 # 테스트 결과 아티팩트 업로드
      if: always() # 테스트 실패 여부와 상관없이 항상 실행
      with:
        name: playwright-report # 아티팩트 이름
        path: playwright-report/ # 리포트가 생성되는 디렉토리
        retention-days: 30 # 아티팩트 보관 기간 (30일)

이 워크플로우는 main 또는 develop 브랜치에 코드가 푸시되거나 풀 리퀘스트가 생성/업데이트될 때마다 자동으로 실행됩니다. Playwright 테스트가 실행된 후, playwright-report 디렉토리에 생성된 HTML 리포트는 GitHub Actions의 아티팩트로 업로드되어 누구나 다운로드하여 결과를 확인할 수 있습니다. 이처럼 CI/CD와 E2E 테스트를 연동하면, 개발팀은 코드 변경이 서비스에 미치는 영향을 즉각적으로 파악하고, 문제 발생 시 신속하게 대응할 수 있습니다.

테스트 결과 리포팅 및 분석: 문제점을 한눈에 파악하는 방법

E2E 테스트를 성공적으로 실행하는 것만큼 중요한 것이 바로 테스트 결과 리포팅입니다. 효과적인 리포팅은 테스트의 성공 여부를 명확히 보여주고, 실패한 테스트의 원인을 빠르게 분석하여 문제 해결 시간을 단축시키는 데 필수적인 역할을 합니다.

Playwright 내장 HTML 리포터 활용

Playwright는 기본적으로 강력한 HTML 리포터를 제공합니다. 이 리포터는 테스트 실행 후 playwright-report/ 디렉토리에 생성되며, 테스트 결과를 웹 페이지 형태로 시각적으로 보여줍니다. npm test 실행 후 playwright show-report 명령을 통해 언제든지 리포트를 브라우저로 열어볼 수 있습니다.

Playwright HTML 리포터의 주요 특징은 다음과 같습니다.

  • 테스트 요약: 전체 테스트 수, 통과/실패/스킵된 테스트 수 등을 한눈에 파악할 수 있습니다.
  • 개별 테스트 상세 정보: 각 테스트 케이스를 클릭하면 실행 시간, 단계별 로그, 사용된 브라우저, 실패 시 에러 메시지 등을 상세히 볼 수 있습니다.
  • 스크린샷 및 비디오: 테스트가 실패했을 때, Playwright는 자동으로 해당 시점의 스크린샷을 캡처하고 비디오를 녹화할 수 있습니다. 이 기능은 실패 원인을 시각적으로 파악하는 데 결정적인 도움을 줍니다.
  • 트레이스 뷰어: playwright test --trace on 옵션으로 실행하면 테스트 실행 전체 과정을 녹화한 트레이스 파일을 생성합니다. 이를 Playwright의 트레이스 뷰어(playwright show-trace trace.zip)로 열면 각 액션의 스크린샷, DOM 스냅샷, 네트워크 요청, 콘솔 로그 등 마치 타임머신을 타고 과거로 돌아간 것처럼 상세하게 디버깅할 수 있습니다.

이러한 내장 리포팅 기능만으로도 대부분의 프로젝트에서 충분한 정보를 얻을 수 있습니다. CI/CD 파이프라인에 이 HTML 리포트를 아티팩트로 저장하면, 개발팀은 언제든지 빌드 결과를 통해 테스트 결과를 확인할 수 있습니다.

고급 리포팅 도구 연동 (Allure Report 예시)

프로젝트 규모가 커지거나, 보다 다양한 통계 및 시각화 기능이 필요하다면 Allure Report와 같은 고급 리포팅 도구를 Playwright와 연동할 수 있습니다.

Allure Report는 테스트 결과를 통합하고 풍부한 시각화 기능을 제공하는 오픈소스 프레임워크입니다. Playwright와 Allure를 연동하면 다음과 같은 고급 리포팅이 가능해집니다.

  • 대시보드: 테스트 실행 이력, 통과율 추이, 가장 많이 실패하는 테스트 목록 등을 한눈에 볼 수 있는 대시보드를 제공합니다.
  • 테스트 케이스 상세: 각 테스트 케이스에 대한 상세한 설명, 단계별 실행 결과, 첨부 파일(스크린샷, 비디오), 환경 정보 등을 포함합니다.
  • 필터링 및 검색: 태그, 심각도, 상태 등 다양한 기준으로 테스트 결과를 필터링하고 검색할 수 있습니다.
  • 통합 및 공유: CI/CD 도구와 쉽게 통합되며, 생성된 리포트를 웹 서버에 호스팅하여 팀원들과 쉽게 공유할 수 있습니다.

Allure Report를 Playwright와 연동하려면 allure-playwright 어댑터를 설치하고 Playwright 설정 파일에 추가해야 합니다.


# Allure Report 어댑터 설치
npm install -D allure-playwright

# playwright.config.ts 파일 수정
// reporter 설정
import { defineConfig } from '@playwright/test';

export default defineConfig({
  // ...
  reporter: [
    ['list'], // 콘솔에 리스트 형식으로 출력
    ['html', { open: 'never' }], // 기본 HTML 리포터 (자동으로 열지 않음)
    ['allure-playwright', {
      outputFolder: 'allure-results', // Allure 결과 파일 저장 경로
      detail: true,
      suiteTitle: true,
      categories: true,
      environmentInfo: true,
    }],
  ],
  // ...
});

테스트 실행 후 allure-results 디렉토리에 Allure 결과 파일이 생성됩니다. 이 파일을 기반으로 Allure Report를 생성하고 웹 브라우저로 열 수 있습니다.


# Allure command-line 도구 설치 (처음 한 번만)
npm install -g allure-commandline

# Allure Report 생성 및 열기
allure generate allure-results --clean
allure open

이처럼 고급 리포팅 도구를 활용하면 테스트 결과를 더욱 효과적으로 분석하고, 개발 프로세스의 투명성을 높이며, 팀원 간의 커뮤니케이션을 원활하게 할 수 있습니다. 특히, 실패한 테스트에 대한 상세한 정보를 제공함으로써 디버깅 시간을 크게 단축시키는 데 기여합니다.

Playwright E2E 테스트, 효과적인 운영을 위한 팁

Playwright를 활용한 E2E 테스트 자동화 시스템을 구축하는 것은 시작에 불과합니다. 이 시스템을 장기적으로 효과적으로 운영하고 유지보수하기 위해서는 몇 가지 핵심적인 팁과 전략을 적용해야 합니다.

테스트 데이터 관리 전략

E2E 테스트는 실제와 유사한 데이터를 사용하여 실행되어야 합니다. 그러나 테스트마다 데이터를 수동으로 준비하거나, 테스트 간에 데이터가 겹쳐 오류를 유발하는 경우가 많습니다. 효율적인 테스트 데이터 관리는 견고한 테스트를 위한 필수 요소입니다.

  • 테스트 전 데이터 초기화: 각 테스트 케이스 또는 테스트 스위트가 실행되기 전에 데이터베이스를 초기 상태로 되돌리거나, 필요한 테스트 데이터를 생성하는 방법을 고려해야 합니다. test.beforeEach() 또는 test.beforeAll() 훅을 활용하여 API 호출이나 직접적인 DB 접근을 통해 데이터를 준비할 수 있습니다.
  • 가짜 데이터(Faker) 사용: faker.js와 같은 라이브러리를 사용하여 이름, 이메일, 주소 등 랜덤하고 유니크한 가짜 데이터를 생성합니다. 이는 실제 사용자 데이터와 유사하면서도 테스트 간의 독립성을 보장합니다.
  • 데이터 분리: 테스트 데이터를 코드에 직접 하드코딩하기보다는, 별도의 JSON 파일이나 데이터 모듈로 분리하여 관리합니다. 이는 데이터 변경 시 테스트 코드 전체를 수정할 필요 없이 데이터 파일만 업데이트하면 되므로 유지보수성을 높입니다.
  • 환경별 데이터: 개발, 스테이징, 운영 등 각 환경에 맞는 테스트 데이터를 관리하여, 특정 환경에서만 발생하는 문제를 재현하고 테스트할 수 있도록 합니다.

Page Object Model (POM) 패턴 적용

테스트 코드의 양이 많아질수록 유지보수가 어려워지는 문제가 발생합니다. Page Object Model (POM)은 이러한 문제를 해결하기 위한 디자인 패턴으로, 웹 페이지의 UI 요소를 객체로 추상화하여 테스트 코드와 UI 요소를 분리합니다.

POM 패턴을 적용하면 다음과 같은 이점을 얻을 수 있습니다.

  • 유지보수성 향상: 웹 페이지의 UI가 변경되더라도, 해당 페이지의 Page Object 파일만 수정하면 되므로 모든 테스트 케이스를 수정할 필요가 없습니다.
  • 코드 재사용성: 동일한 UI 요소를 여러 테스트 케이스에서 재사용할 수 있습니다.
  • 가독성 향상: 테스트 코드가 사용자 시나리오에 집중하게 되어, 실제 사용자가 어떻게 웹 페이지와 상호작용하는지 명확하게 이해할 수 있습니다.

예를 들어, 로그인 페이지를 위한 Page Object는 다음과 같이 작성할 수 있습니다.


// pages/LoginPage.ts
import { Page, Locator } from '@playwright/test';

export class LoginPage {
  readonly page: Page;
  readonly usernameInput: Locator;
  readonly passwordInput: Locator;
  readonly loginButton: Locator;
  readonly errorMessage: Locator;

  constructor(page: Page) {
    this.page = page;
    this.usernameInput = page.getByPlaceholder('아이디를 입력하세요');
    this.passwordInput = page.getByPlaceholder('비밀번호를 입력하세요');
    this.loginButton = page.getByRole('button', { name: '로그인' });
    this.errorMessage = page.locator('.error-message');
  }

  async navigate() {
    await this.page.goto('https://www.example.com/login');
  }

  async login(username: string, password: string) {
    await this.usernameInput.fill(username);
    await this.passwordInput.fill(password);
    await this.loginButton.click();
  }

  async getErrorMessage() {
    return await this.errorMessage.textContent();
  }
}

그리고 테스트 코드에서는 이 Page Object를 활용하여 더욱 간결하게 테스트를 작성할 수 있습니다.


// tests/login.spec.ts
import { test, expect } from '@playwright/test';
import { LoginPage } from '../pages/LoginPage'; // LoginPage import

test.describe('로그인 기능 테스트 (POM 적용)', () => {
  let loginPage: LoginPage;

  test.beforeEach(async ({ page }) => {
    loginPage = new LoginPage(page);
    await loginPage.navigate(); // Page Object를 통해 페이지 이동
  });

  test('유효한 자격 증명으로 로그인에 성공해야 한다', async ({ page }) => {
    await loginPage.login('testuser', 'password123');
    await expect(page).toHaveURL('https://www.example.com/dashboard');
  });

  test('잘못된 비밀번호로 로그인 실패 시 에러 메시지를 보여줘야 한다', async () => {
    await loginPage.login('testuser', 'wrongpassword');
    expect(await loginPage.getErrorMessage()).toContain('잘못된 사용자 이름 또는 비밀번호입니다.');
  });
});

이처럼 POM 패턴을 적용하면 테스트 코드의 모듈성확장성이 크게 향상됩니다.

Flaky Test (불안정한 테스트) 관리 전략

Flaky Test는 때로는 통과하고 때로는 실패하는 예측 불가능한 테스트를 의미합니다. 이는 테스트 결과의 신뢰도를 떨어뜨리고 개발팀의 생산성을 저해하는 주범입니다. Playwright는 자동 대기 기능으로 Flaky Test를 줄여주지만, 여전히 발생할 수 있습니다.

  • 원인 분석: Flaky Test의 가장 흔한 원인은 비동기 처리 문제(요소가 로드되기 전에 상호작용 시도), 네트워크 지연, 테스트 환경의 불안정성, 테스트 데이터의 불일치 등입니다. Playwright의 트레이스 뷰어를 활용하여 실패 시점의 상세한 로그와 스크린샷, 네트워크 활동을 분석하는 것이 중요합니다.
  • 명확한 대기 조건: Playwright의 자동 대기 기능이 완벽하지 않을 수도 있습니다. page.waitForSelector(), page.waitForLoadState('networkidle'), expect().toBeVisible() 등 명시적인 대기 조건을 사용하여 요소가 완전히 준비된 후 상호작용하도록 합니다.
  • 테스트 격리: 각 테스트가 이전 테스트의 상태에 의존하지 않도록 독립적으로 실행되게 합니다. test.beforeEach() 훅을 통해 각 테스트 시작 시 필요한 상태를 초기화하고, test.afterEach() 훅을 통해 불필요한 데이터를 정리합니다.
  • 재시도(Retry) 설정: Playwright는 playwright.config.ts 파일에서 테스트 재시도 횟수를 설정할 수 있습니다. 일시적인 네트워크 문제 등으로 인한 Flaky Test를 줄이는 데 도움이 되지만, 근본적인 원인 해결 없이 남용하는 것은 좋지 않습니다.
  • 병렬 실행 최적화: 병렬 실행 시 테스트 간의 의존성이나 자원 경합이 발생하지 않도록 주의합니다. 컨테이너 환경에서 각 테스트 워커가 충분한 자원을 할당받도록 설정하는 것도 중요합니다.

Flaky Test는 개발팀의 신뢰를 무너뜨리므로, 적극적으로 식별하고 해결하는 노력이 필요합니다. 지속적인 모니터링과 분석을 통해 테스트 스위트의 안정성을 높여나가야 합니다.

결론: Playwright로 더욱 견고한 웹 서비스를 구축하세요

지금까지 Playwright를 활용하여 웹 애플리케이션의 E2E 테스트 자동화 시스템을 구축하는 방법부터, CI/CD 파이프라인에 연동하여 개발 워크플로우를 최적화하고, 효과적인 리포팅을 통해 문제점을 신속하게 파악하는 방법, 그리고 장기적인 운영 팁까지 상세하게 살펴보았습니다.

Playwright는 강력한 크로스 브라우저 지원, 지능적인 자동 대기, 뛰어난 병렬 실행 성능, 그리고 다양한 언어 지원을 통해 웹 애플리케이션의 E2E 테스트를 안정적이고 효율적으로 수행할 수 있도록 돕는 최적의 도구입니다. CI/CD 환경에 통합하여 코드 변경 시마다 자동으로 테스트를 실행하고, 상세한 리포팅을 통해 신속하게 피드백을 받는 과정은 개발팀의 생산성을 극대화하고 서비스의 품질을 한 차원 높이는 데 결정적인 역할을 합니다.

물론 E2E 테스트 자동화는 초기 설정과 테스트 코드 작성에 일정 수준의 노력이 필요합니다. 하지만 장기적으로는 수동 테스트의 반복적인 부담을 줄이고, 버그를 조기에 발견하여 수정 비용을 절감하며, 궁극적으로는 사용자에게 더 안정적이고 만족스러운 서비스를 제공하는 기반이 될 것입니다.

이제 Playwright를 활용하여 여러분의 웹 애플리케이션 개발 프로세스에 E2E 테스트 자동화를 도입하고, 더욱 견고하고 신뢰할 수 있는 웹 서비스를 구축해 보시기 바랍니다. 이 가이드가 여러분의 여정에 도움이 되었기를 바랍니다.

Playwright를 활용한 E2E 테스트 자동화에 대해 궁금한 점이나, 실제 프로젝트에 적용하면서 겪었던 흥미로운 경험이 있다면 댓글로 공유해 주세요. 함께 더 나은 개발 문화를 만들어갈 수 있기를 기대합니다!

📌 함께 읽으면 좋은 글

  • [클라우드 인프라] 클라우드 비용, 더 이상 새는 돈은 없다! FinOps로 최적화하는 절감 전략
  • [보안] HTTP 보안 헤더로 웹 애플리케이션 방어막 구축하기: 실전 적용 후기
  • [튜토리얼] Minikube 로컬 쿠버네티스 개발 환경 구축부터 애플리케이션 배포까지 완벽 가이드

이 글이 도움이 되셨다면 공감(♥)댓글로 응원해 주세요!
궁금한 점이나 다루었으면 하는 주제가 있다면 댓글로 남겨주세요.

반응형