튜토리얼

Playwright 활용 웹 애플리케이션 E2E 테스트: 효율적인 환경 구축 및 실전 가이드

강코의 코딩 일기 2026. 6. 6. 12:15
반응형

Playwright를 활용하여 웹 애플리케이션의 End-to-End 테스트 환경을 효율적으로 구축하고 실전 테스트를 수행하는 방법을 상세히 안내합니다. Cypress, Selenium과의 비교를 통해 Playwright의 강력한 장점을 알아보세요.

웹 애플리케이션 개발 과정에서 사용자 경험의 중요성은 아무리 강조해도 지나치지 않습니다. 완벽하게 작동하는 것처럼 보이는 기능도 실제 사용자의 흐름에서는 예상치 못한 문제를 일으킬 수 있습니다. 이러한 문제점을 사전에 발견하고 수정하는 가장 효과적인 방법 중 하나가 바로 End-to-End (E2E) 테스트입니다. E2E 테스트는 사용자가 애플리케이션과 상호작용하는 모든 과정을 처음부터 끝까지 시뮬레이션하여 시스템 전체의 무결성을 검증합니다.

그러나 E2E 테스트 환경을 구축하고 유지하는 것은 결코 쉬운 일이 아닙니다. 브라우저 호환성, 비동기 처리, 테스트의 안정성 등 다양한 난관에 부딪히기 마련입니다. 이러한 복잡성을 해결하고 개발팀의 생산성을 극대화할 수 있는 강력한 도구로 Playwright가 주목받고 있습니다. Microsoft에서 개발한 Playwright는 현대 웹 애플리케이션 테스트에 최적화된 다양한 기능을 제공하며, 빠르고 안정적인 E2E 테스트 환경 구축을 지원합니다.

본 가이드에서는 Playwright를 활용하여 웹 애플리케이션의 E2E 테스트 환경을 구축하고, 실제 시나리오에 기반한 테스트를 작성하는 방법을 상세히 다룹니다. 또한, Playwright의 핵심 기능과 장점을 살펴보고, 널리 사용되는 다른 E2E 테스트 프레임워크와의 비교를 통해 Playwright가 왜 탁월한 선택이 될 수 있는지 객관적으로 분석합니다. 이 글을 통해 여러분의 웹 애플리케이션이 더욱 견고하고 신뢰성 있는 사용자 경험을 제공할 수 있도록 Playwright를 효과적으로 도입하는 데 필요한 통찰력을 얻어가시길 바랍니다.

📑 목차

Playwright를 활용한 웹 애플리케이션 End-to-End 테스트 환경 구축 및 실습 가이드 - covid, testing, corona test, covid-19, corona, coronavirus, sars-cov-2, concept, quick test, pcr, pcr-test, covid test, covid, covid, covid, covid, covid, corona, corona, covid test, covid test, covid test

Image by analogicus on Pixabay

Playwright란 무엇인가? 핵심 특징 및 장점

Playwright는 Microsoft에서 개발한 오픈소스 Node.js 라이브러리로, Chromium, Firefox, WebKit을 포함한 모든 주요 브라우저에서 웹 애플리케이션을 테스트하고 자동화할 수 있도록 설계되었습니다. 처음부터 현대 웹의 복잡성을 처리하도록 구축되었으며, 빠르고 안정적인 테스트 실행을 목표로 합니다. Playwright가 제공하는 핵심 특징과 장점은 다음과 같습니다.

다중 브라우저 및 플랫폼 지원

  • 크로스 브라우저 호환성: Playwright는 단일 API로 Chromium (Chrome, Edge), Firefox, WebKit (Safari)을 지원합니다. 이는 개발자가 각 브라우저별로 별도의 테스트 코드를 작성할 필요 없이, 다양한 브라우저 환경에서 애플리케이션의 동작을 검증할 수 있게 합니다.
  • 크로스 플랫폼 지원: Windows, macOS, Linux 등 다양한 운영체제에서 원활하게 작동합니다. 컨테이너 환경이나 CI/CD 파이프라인에서도 쉽게 통합하여 사용할 수 있습니다.
  • 멀티 언어 지원: TypeScript, JavaScript는 물론 Python, .NET, Java 등 다양한 프로그래밍 언어를 지원하여 개발팀의 기술 스택에 맞춰 유연하게 선택할 수 있습니다.

강력한 자동화 및 테스트 기능

  • 자동 대기 (Auto-wait): Playwright는 요소가 DOM에 나타나거나, 활성화되거나, 애니메이션이 완료될 때까지 자동으로 기다립니다. 이는 테스트가 불안정해지는 주된 원인인 비동기 타이밍 문제를 크게 줄여주어 테스트의 안정성을 향상시킵니다.
  • 격리된 브라우저 컨텍스트: 각 테스트는 완전히 격리된 브라우저 컨텍스트에서 실행됩니다. 이는 테스트 간의 상태 간섭을 방지하고, 테스트의 독립성과 신뢰성을 보장합니다.
  • 병렬 테스트 실행: 기본적으로 병렬 테스트 실행을 지원하여, 여러 테스트를 동시에 실행함으로써 전체 테스트 시간을 획기적으로 단축할 수 있습니다. 이는 특히 대규모 프로젝트에서 테스트 효율성을 높이는 데 기여합니다.
  • 강력한 셀렉터: CSS, XPath뿐만 아니라 텍스트, 역할, 대체 텍스트 등 다양한 속성을 기반으로 요소를 선택할 수 있어 견고하고 유연한 셀렉터 전략을 구축할 수 있습니다.
  • 풍부한 디버깅 도구: Playwright Inspector를 통해 스텝별 실행, DOM 탐색, 액션 로그 확인 등 강력한 디버깅 기능을 제공합니다. 또한, 테스트 실패 시 자동으로 스크린샷과 비디오를 기록하여 문제 원인 파악을 용이하게 합니다.

이러한 특징들은 Playwright가 현대 웹 애플리케이션의 복잡한 요구사항을 충족시키면서도, 개발자가 빠르고 안정적인 E2E 테스트를 작성하고 유지보수할 수 있도록 돕는 핵심적인 요소입니다.

경쟁 도구 비교: Playwright vs. Cypress vs. Selenium

웹 애플리케이션 E2E 테스트 도구는 Playwright 외에도 Cypress, Selenium 등 다양한 선택지가 있습니다. 각각의 도구는 고유한 아키텍처와 특징을 가지고 있으며, 프로젝트의 요구사항과 팀의 선호도에 따라 적합한 도구가 달라질 수 있습니다. 여기서는 Playwright, Cypress, Selenium 세 가지 주요 도구를 객관적인 관점에서 비교 분석합니다.

특징 Playwright Cypress Selenium
아키텍처 Node.js 프로세스에서 브라우저와 직접 통신. WebDriver 프로토콜을 사용하지 않음. 브라우저 내부에서 직접 실행. 앱과 동일한 런타임에서 작동. WebDriver 프로토콜을 통해 브라우저 드라이버와 통신.
브라우저 지원 Chromium, Firefox, WebKit (Safari) 모두 지원. 진정한 크로스 브라우저. Chromium 기반 브라우저 (Chrome, Edge), Firefox, Electron 지원. WebKit은 제한적. 모든 주요 브라우저 지원 (별도 드라이버 필요).
언어 지원 TypeScript, JavaScript, Python, .NET, Java TypeScript, JavaScript Java, Python, C#, Ruby, JavaScript 등 다수
병렬 테스트 기본적으로 강력한 병렬 실행 지원. Sharding 가능. 개별 테스트 파일 단위 병렬 실행 가능 (유료 서비스 또는 셋업 필요). Selenium Grid를 통해 강력한 병렬 실행 지원.
자동 대기 (Auto-wait) 기본적으로 모든 액션에 자동 대기 기능 내장. 기본적으로 자동 대기 기능 내장. 명시적/암시적 대기 코드 필요.
iframe 및 새 탭 처리 매우 안정적이고 쉬운 처리. iframe 처리 가능, 새 탭은 테스트 불가 (동일 오리진 정책). iframe 및 새 탭 처리 가능 (별도 코드 필요).
디버깅 도구 Playwright Inspector, VS Code 확장, 트레이스 뷰어. Cypress Test Runner UI (실시간 리로드, 타임 트래블 디버깅). 브라우저 개발자 도구, IDE 디버거.
학습 곡선 비교적 낮음. 명확한 API와 좋은 문서. 낮음. 직관적인 API와 훌륭한 개발자 경험. 높음. WebDriver 개념 이해와 환경 설정 복잡성.

비교 분석 요약 및 Playwright의 강점

  • Playwright크로스 브라우저 테스트에 있어 가장 강력한 면모를 보입니다. 단일 코드베이스로 Chromium, Firefox, WebKit을 모두 지원하며, Selenium처럼 별도의 드라이버 관리가 필요하지 않습니다. Cypress가 WebKit 지원에 제한적인 반면, Playwright는 진정한 의미의 크로스 브라우저 호환성을 제공합니다.
  • 성능과 안정성 측면에서 Playwright의 자동 대기 기능격리된 브라우저 컨텍스트는 테스트의 Flakiness (불안정성)를 현저히 줄여줍니다. Selenium은 명시적인 대기 로직이 필요하여 테스트 코드가 복잡해질 수 있고, Cypress는 브라우저 내부에서 실행되어 일부 시나리오 (예: 새 탭)에서 제약이 있습니다.
  • 병렬 테스트는 Playwright의 또 다른 강점입니다. 내장된 병렬 실행 기능은 대규모 테스트 스위트의 실행 시간을 드라마틱하게 단축시켜 개발 프로세스의 효율성을 높입니다. Selenium도 Grid를 통해 병렬 실행을 지원하지만, 설정이 복잡한 편입니다.
  • 디버깅 경험 또한 Playwright는 훌륭합니다. Playwright Inspector는 테스트 실행 과정을 시각적으로 추적하고 디버깅하는 데 큰 도움을 줍니다. Cypress의 타임 트래블 디버깅도 훌륭하지만, Playwright는 더 넓은 범위의 브라우저에서 유사한 수준의 디버깅 경험을 제공합니다.

결론적으로, Playwright는 현대 웹 애플리케이션의 복잡한 테스트 요구사항을 충족시키면서도, 개발자에게 높은 생산성과 안정성을 제공하는 강력한 E2E 테스트 도구입니다. 특히 광범위한 브라우저 지원뛰어난 병렬 처리 능력이 필요한 프로젝트라면 Playwright가 가장 이상적인 선택이 될 수 있습니다.

Playwright 개발 환경 구축: 시작하기

이제 Playwright를 사용하여 웹 애플리케이션 E2E 테스트 환경을 구축하는 방법을 단계별로 살펴보겠습니다. Playwright는 Node.js 기반이므로, 먼저 Node.js가 설치되어 있어야 합니다.

1. Node.js 설치 확인

터미널 또는 명령 프롬프트에서 다음 명령어를 실행하여 Node.js 설치 여부를 확인합니다. 설치되어 있지 않다면, Node.js 공식 웹사이트에서 다운로드하여 설치합니다.

node -v
npm -v

2. Playwright 프로젝트 초기화

테스트를 진행할 프로젝트 폴더로 이동하거나, 새로운 폴더를 생성한 후 다음 명령어를 실행하여 Playwright를 설치하고 프로젝트를 초기화합니다.

npm init playwright@latest

이 명령어는 Playwright를 설치하고, 몇 가지 질문을 통해 기본적인 프로젝트 구조를 설정해 줍니다. 예를 들어, TypeScript 사용 여부, 테스트 파일 위치, GitHub Actions 워크플로우 추가 여부 등을 묻습니다. 대부분의 경우 기본값을 선택해도 무방합니다.

  • 프로젝트 초기화 시 생성되는 주요 파일 및 폴더:
    • playwright.config.ts: Playwright 설정 파일
    • tests/: 테스트 파일들이 저장될 기본 폴더
    • package.json: 프로젝트 의존성 관리 파일
    • example.spec.ts (또는 .js): Playwright가 제공하는 예제 테스트 파일

3. Playwright 설정 파일 (playwright.config.ts) 이해하기

playwright.config.ts 파일은 Playwright 테스트 실행의 전반적인 설정을 정의합니다. 다음은 주요 설정 옵션입니다.

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

export default defineConfig({
  testDir: './tests', // 테스트 파일이 위치한 디렉토리
  fullyParallel: true, // 테스트를 완전히 병렬로 실행할지 여부
  forbidOnly: !!process.env.CI, // CI 환경에서 .only() 사용 금지
  retries: process.env.CI ? 2 : 0, // CI 환경에서 실패한 테스트 재시도 횟수
  workers: process.env.CI ? 1 : undefined, // CI 환경에서 동시에 실행할 워커 수
  reporter: 'html', // 테스트 결과 리포터 (html, list, dot 등)
  use: {
    baseURL: 'http://127.0.0.1:3000', // 테스트할 웹 애플리케이션의 기본 URL
    trace: 'on-first-retry', // 테스트 실패 시 트레이스 기록 (off, on, on-first-retry, retain-on-failure)
  },

  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
    {
      name: 'firefox',
      use: { ...devices['Desktop Firefox'] },
    },
    {
      name: 'webkit',
      use: { ...devices['Desktop Safari'] },
    },
    // 모바일 뷰포트 테스트 예시
    // {
    //   name: 'Mobile Chrome',
    //   use: { ...devices['Pixel 5'] },
    // },
    // {
    //   name: 'Mobile Safari',
    //   use: { ...devices['iPhone 12'] },
    // },
  ],

  // 웹 서버를 시작하는 설정 (테스트 전에 애플리케이션 실행)
  webServer: {
    command: 'npm run start', // 웹 애플리케이션 시작 명령어
    url: 'http://127.0.0.1:3000', // 웹 애플리케이션 URL
    reuseExistingServer: !process.env.CI, // CI가 아니면 기존 서버 재사용
  },
});

주요 설정 항목 설명:

  • testDir: Playwright가 테스트 파일을 찾는 디렉토리입니다. 기본값은 ./tests입니다.
  • fullyParallel: true로 설정하면 모든 테스트 파일을 병렬로 실행하여 테스트 시간을 단축합니다.
  • retries: 테스트 실패 시 재시도 횟수를 설정합니다. 불안정한 테스트를 처리하는 데 유용합니다.
  • reporter: 테스트 결과 보고서 형식을 지정합니다. 'html'은 시각적인 보고서를 생성합니다.
  • use.baseURL: 테스트할 웹 애플리케이션의 기본 URL을 설정합니다. 테스트 코드에서 page.goto('/')와 같이 상대 경로를 사용할 수 있게 합니다.
  • projects: 여러 브라우저 (Chromium, Firefox, WebKit) 및 뷰포트 (Desktop, Mobile)에서 테스트를 실행하도록 정의합니다. 각 프로젝트는 독립적으로 실행됩니다.
  • webServer: E2E 테스트를 시작하기 전에 로컬 개발 서버를 자동으로 실행하도록 설정할 수 있습니다. command에 서버 시작 명령어를, url에 서버의 주소를 지정합니다.

이 설정을 통해 여러분은 다양한 환경에서 안정적이고 효율적인 E2E 테스트를 수행할 수 있는 기반을 마련하게 됩니다.

Playwright를 활용한 웹 애플리케이션 End-to-End 테스트 환경 구축 및 실습 가이드 - test, virus, coronavirus, self-test, covid-19, infection, lock down, hygiene, transmission, shutdown, pandemic, test, test, test, test, test, virus, virus, virus, virus, coronavirus, coronavirus, coronavirus, coronavirus, covid-19, covid-19, covid-19, covid-19, pandemic, pandemic

Image by Alexandra_Koch on Pixabay

Playwright를 활용한 E2E 테스트 실전 가이드

환경 설정이 완료되었다면, 이제 Playwright를 사용하여 실제 웹 애플리케이션을 테스트하는 방법을 실습해 볼 차례입니다. 기본적인 페이지 이동부터 사용자 인터랙션, 그리고 페이지 오브젝트 모델 (Page Object Model)을 적용하는 방법까지 다룹니다.

1. 첫 번째 테스트 작성하기: 페이지 접속 및 요소 확인

tests 폴더 안에 example.spec.ts 파일을 열거나, 새로 login.spec.ts와 같은 파일을 생성하여 다음 코드를 작성해 보세요. 이 예제는 특정 페이지에 접속하여 제목을 확인하고, 특정 텍스트를 포함하는 요소가 존재하는지 확인하는 간단한 테스트입니다.

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

test.describe('로그인 페이지 테스트', () => {
  test('로그인 페이지가 올바르게 로드되어야 한다', async ({ page }) => {
    // 1. 테스트할 웹 애플리케이션의 로그인 페이지로 이동합니다.
    // baseURL이 playwright.config.ts에 설정되어 있다면 상대 경로 사용 가능
    await page.goto('/login');

    // 2. 페이지의 제목이 올바른지 검증합니다.
    await expect(page).toHaveTitle(/로그인|Login/); // 정규식을 사용하여 유연하게 검증

    // 3. '환영합니다' 텍스트를 포함하는 요소가 존재하는지 검증합니다.
    await expect(page.getByText('환영합니다')).toBeVisible();

    // 4. 아이디 입력 필드가 존재하는지 검증합니다.
    await expect(page.getByLabel('아이디')).toBeVisible();

    // 5. 비밀번호 입력 필드가 존재하는지 검증합니다.
    await expect(page.getByLabel('비밀번호')).toBeVisible();

    // 6. 로그인 버튼이 존재하는지 검증합니다.
    await expect(page.getByRole('button', { name: '로그인' })).toBeVisible();
  });
});

코드 설명:

  • test.describe('...', () => { ... });: 여러 관련 테스트를 그룹화합니다.
  • test('...', async ({ page }) => { ... });: 단일 테스트 케이스를 정의합니다. { page }는 Playwright에서 제공하는 페이지 객체입니다.
  • await page.goto('/login');: 지정된 URL로 이동합니다.
  • await expect(page).toHaveTitle(/로그인|Login/);: 현재 페이지의 제목이 '로그인' 또는 'Login'을 포함하는지 검증합니다. expect는 Playwright의 내장 어설션 라이브러리입니다.
  • page.getByText('환영합니다'): 텍스트 내용으로 요소를 찾습니다. Playwright의 강력한 Locator 중 하나입니다.
  • page.getByLabel('아이디'): 라벨 텍스트로 입력 필드를 찾습니다.
  • page.getByRole('button', { name: '로그인' }): ARIA role과 접근 가능한 이름으로 버튼을 찾습니다. 이는 접근성 (Accessibility) 관점에서도 좋은 테스트 작성 방법입니다.

2. 사용자 인터랙션 시뮬레이션: 로그인 기능 테스트

이번에는 실제 사용자처럼 입력 필드에 값을 입력하고 버튼을 클릭하는 테스트를 작성해 보겠습니다.

// tests/login.spec.ts (이전 코드에 추가)
import { test, expect } from '@playwright/test';

test.describe('로그인 기능 테스트', () => {
  test.beforeEach(async ({ page }) => {
    // 각 테스트 케이스 시작 전 로그인 페이지로 이동
    await page.goto('/login');
  });

  test('유효한 자격 증명으로 로그인이 성공해야 한다', async ({ page }) => {
    // 1. 아이디 입력 필드에 값을 입력합니다.
    await page.getByLabel('아이디').fill('testuser');

    // 2. 비밀번호 입력 필드에 값을 입력합니다.
    await page.getByLabel('비밀번호').fill('password123');

    // 3. 로그인 버튼을 클릭합니다.
    await page.getByRole('button', { name: '로그인' }).click();

    // 4. 로그인 성공 후 이동될 페이지의 URL을 검증합니다.
    await expect(page).toHaveURL(/dashboard/); // 대시보드 페이지로 이동했는지 확인

    // 5. 로그인 성공 후 나타나는 환영 메시지를 검증합니다.
    await expect(page.getByText('안녕하세요, testuser님!')).toBeVisible();
  });

  test('유효하지 않은 자격 증명으로 로그인이 실패해야 한다', async ({ page }) => {
    await page.getByLabel('아이디').fill('invaliduser');
    await page.getByLabel('비밀번호').fill('wrongpassword');
    await page.getByRole('button', { name: '로그인' }).click();

    // 1. 로그인 실패 메시지가 나타나는지 검증합니다.
    await expect(page.getByText('아이디 또는 비밀번호가 올바르지 않습니다.')).toBeVisible();

    // 2. 여전히 로그인 페이지에 머물러 있는지 URL을 검증합니다.
    await expect(page).toHaveURL(/login/);
  });
});

새로운 코드 설명:

  • test.beforeEach(async ({ page }) => { ... });: 각 테스트 케이스가 실행되기 전에 공통적으로 수행할 작업을 정의합니다. 여기서는 로그인 페이지로 이동하는 작업을 수행하여 테스트의 반복성을 높입니다.
  • await page.getByLabel('아이디').fill('testuser');: 입력 필드를 찾아 지정된 텍스트를 입력합니다.
  • await page.getByRole('button', { name: '로그인' }).click();: 버튼을 클릭합니다. Playwright는 클릭하기 전에 요소가 가시적이고 활성화될 때까지 자동으로 기다립니다.
  • await expect(page).toHaveURL(/dashboard/);: 현재 페이지의 URL이 특정 패턴과 일치하는지 검증합니다.

3. 테스트 실행 및 결과 확인

터미널에서 다음 명령어를 실행하여 작성한 테스트를 실행합니다.

npx playwright test

특정 브라우저에서만 실행하거나, 헤드리스 모드를 끄고 브라우저를 직접 보면서 실행하고 싶다면:

npx playwright test --project=chromium
npx playwright test --headed

테스트 실행이 완료되면, playwright.config.tsreporter: 'html'로 설정했다면 HTML 보고서가 생성됩니다. 다음 명령어로 보고서를 열 수 있습니다.

npx playwright show-report

이 보고서는 각 테스트의 성공/실패 여부, 실행 시간, 로그, 스크린샷, 비디오, 트레이스 파일 등 상세한 정보를 제공하여 디버깅 및 문제 파악에 매우 유용합니다.

Playwright를 활용한 웹 애플리케이션 End-to-End 테스트 환경 구축 및 실습 가이드 - coronavirus, mass testing, covid-19, slovakia, swab test, swab testing, pandemic, new normal, antigen test, man, testing, coronavirus test, medical worker, healthcare professional, healthcare worker, face masks, žilina, slovakia, slovakia, slovakia, swab test, swab test, swab test, swab test, swab test, pandemic, antigen test, antigen test, antigen test, testing, testing, coronavirus test, coronavirus test, medical worker, healthcare professional, healthcare worker, healthcare worker

Image by lukasmilan on Pixabay

고급 기능 활용 및 테스트 효율화 전략

Playwright는 단순히 웹 페이지를 자동화하는 것을 넘어, 복잡한 테스트 시나리오를 효율적으로 구현하고 테스트의 신뢰성을 높일 수 있는 다양한 고급 기능을 제공합니다.

1. Page Object Model (POM) 적용

대규모 애플리케이션의 E2E 테스트를 작성할 때, 테스트 코드가 길어지고 유지보수가 어려워지는 문제가 발생할 수 있습니다. Page Object Model (POM)은 이러한 문제를 해결하기 위한 디자인 패턴입니다. 각 웹 페이지를 객체로 추상화하여, 페이지의 요소와 그 페이지에서 수행할 수 있는 액션을 메서드로 캡슐화합니다.

POM 구현 예시: 로그인 페이지

pages 폴더를 생성하고 LoginPage.ts 파일을 만듭니다.

// pages/LoginPage.ts
import { type Page, type 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.getByLabel('아이디');
    this.passwordInput = page.getByLabel('비밀번호');
    this.loginButton = page.getByRole('button', { name: '로그인' });
    this.errorMessage = page.getByText('아이디 또는 비밀번호가 올바르지 않습니다.');
  }

  async goto() {
    await this.page.goto('/login');
  }

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

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

이제 테스트 파일에서 LoginPage 객체를 사용하여 테스트를 작성할 수 있습니다.

// tests/login.spec.ts (POM 적용)
import { test, expect } from '@playwright/test';
import { LoginPage } from '../pages/LoginPage'; // LoginPage 임포트

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

  test.beforeEach(async ({ page }) => {
    loginPage = new LoginPage(page);
    await loginPage.goto();
  });

  test('유효한 자격 증명으로 로그인이 성공해야 한다', async ({ page }) => {
    await loginPage.login('testuser', 'password123');
    await expect(page).toHaveURL(/dashboard/);
    await expect(page.getByText('안녕하세요, testuser님!')).toBeVisible();
  });

  test('유효하지 않은 자격 증명으로 로그인이 실패해야 한다', async ({ page }) => {
    await loginPage.login('invaliduser', 'wrongpassword');
    await expect(loginPage.errorMessage).toBeVisible();
    await expect(page).toHaveURL(/login/);
  });
});

POM을 사용하면 테스트 코드가 가독성이 높아지고, UI 변경이 발생했을 때 해당 페이지 객체만 수정하면 되므로 유지보수가 훨씬 용이해집니다.

2. Fixtures를 활용한 테스트 컨텍스트 관리

Playwright의 fixtures는 테스트 간에 공유되는 설정, 리소스, 상태를 효율적으로 관리하는 강력한 방법입니다. 예를 들어, 로그인된 상태로 테스트를 시작해야 하는 경우 Fixtures를 사용하여 로그인 과정을 캡슐화할 수 있습니다.

// tests/auth.setup.ts (인증 상태를 저장하는 파일)
import { test as setup, expect } from '@playwright/test';

const authFile = 'playwright/.auth/user.json'; // 인증 정보 저장 경로

setup('인증 설정: 일반 사용자 로그인', async ({ page }) => {
  await page.goto('/login');
  await page.getByLabel('아이디').fill('testuser');
  await page.getByLabel('비밀번호').fill('password123');
  await page.getByRole('button', { name: '로그인' }).click();
  await page.waitForURL('/dashboard'); // 대시보드로 이동할 때까지 대기
  await expect(page.getByText('안녕하세요, testuser님!')).toBeVisible();

  // 현재 브라우저 상태 (쿠키, 로컬 스토리지 등)를 파일로 저장
  await page.context().storageState({ path: authFile });
});

playwright.config.ts 파일에 이 setup 파일을 추가하여 모든 테스트 전에 실행되도록 설정합니다.

// playwright.config.ts (일부)
projects: [
  // Setup project
  {
    name: 'setup',
    testMatch: /.*\.setup\.ts/, // .setup.ts 파일만 실행
  },

  {
    name: 'chromium',
    use: {
      ...devices['Desktop Chrome'],
      storageState: 'playwright/.auth/user.json', // setup에서 저장한 인증 상태 사용
    },
    dependencies: ['setup'], // 'setup' 프로젝트가 먼저 실행되도록 의존성 설정
  },
  // ... firefox, webkit 프로젝트도 동일하게 설정
],

이제 다른 테스트에서는 별도의 로그인 과정 없이 바로 로그인된 상태로 테스트를 시작할 수 있습니다.

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

test.describe('대시보드 페이지 테스트', () => {
  test('로그인된 사용자는 대시보드를 볼 수 있어야 한다', async ({ page }) => {
    await page.goto('/dashboard');
    await expect(page.getByText('대시보드 통계')).toBeVisible();
    await expect(page.getByRole('heading', { name: '최근 활동' })).toBeVisible();
  });
});

Fixtures를 사용하면 테스트 간의 중복 코드를 줄이고, 테스트의 실행 속도를 향상시키며, 테스트 환경을 일관되게 유지하는 데 큰 도움이 됩니다.

3. 시각적 회귀 테스트 (Visual Regression Testing)

웹 애플리케이션의 UI/UX가 변경될 때, 기능적으로는 문제가 없지만 시각적인 오류가 발생하는 경우가 있습니다. 시각적 회귀 테스트는 이러한 문제를 자동으로 감지하는 데 사용됩니다. Playwright는 스크린샷 기능을 통해 시각적 회귀 테스트를 쉽게 구현할 수 있습니다.

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

test.describe('시각적 회귀 테스트', () => {
  test('홈페이지 UI는 기준 스크린샷과 일치해야 한다', async ({ page }) => {
    await page.goto('/');
    // 페이지 전체 스크린샷을 찍고 기준 이미지와 비교합니다.
    await expect(page).toHaveScreenshot('homepage.png', { maxDiffPixelRatio: 0.05 });
  });

  test('로그인 페이지 UI는 기준 스크린샷과 일치해야 한다', async ({ page }) => {
    await page.goto('/login');
    // 특정 요소만 스크린샷을 찍고 비교할 수도 있습니다.
    await expect(page.getByRole('form', { name: '로그인 폼' })).toHaveScreenshot('login-form.png');
  });
});

maxDiffPixelRatio 옵션은 허용 가능한 픽셀 차이 비율을 설정합니다. 테스트를 처음 실행하면 기준 스크린샷이 tests/visual.spec.ts-snapshots 폴더에 생성됩니다. 이후 테스트 실행 시 새로운 스크린샷을 찍어 기준 스크린샷과 비교하여 차이가 발생하면 테스트가 실패합니다. 이는 예기치 않은 UI 변경을 빠르게 감지하는 데 매우 효과적입니다.

이러한 고급 기능들을 적절히 활용하면 Playwright를 통해 더욱 견고하고 효율적인 E2E 테스트 전략을 구축할 수 있습니다. 특히 CI/CD 파이프라인에 통합하여 자동화된 테스트를 실행함으로써 개발 워크플로우를 크게 개선할 수 있습니다.

결론: Playwright로 완성하는 견고한 웹 애플리케이션

지금까지 Playwright를 활용하여 웹 애플리케이션의 End-to-End 테스트 환경을 구축하고, 실제 테스트를 작성하며, 나아가 고급 기능들을 통해 테스트의 효율성과 안정성을 높이는 방법을 상세히 살펴보았습니다. Playwright는 현대 웹 개발 환경의 복잡성을 이해하고 이를 해결하기 위해 설계된 강력한 도구입니다.

Playwright의 주요 강점은 다음과 같습니다:

  • 진정한 크로스 브라우저 지원: Chromium, Firefox, WebKit을 모두 지원하여 다양한 사용자 환경을 포괄합니다.
  • 뛰어난 안정성: 자동 대기 기능과 격리된 컨텍스트를 통해 테스트의 불안정성을 최소화합니다.
  • 높은 생산성: 직관적인 API, 강력한 디버깅 도구, 병렬 테스트 실행으로 개발자의 생산성을 향상시킵니다.
  • 유연한 확장성: Page Object Model, Fixtures 등 다양한 디자인 패턴과 기능을 통해 복잡한 시나리오도 효과적으로 관리할 수 있습니다.

E2E 테스트는 애플리케이션의 품질을 보장하고 사용자에게 신뢰할 수 있는 경험을 제공하는 데 필수적인 요소입니다. 수동 테스트에만 의존하거나, 단위/통합 테스트만으로는 발견하기 어려운 잠재적인 문제들을 Playwright를 통한 자동화된 E2E 테스트로 효과적으로 식별하고 해결할 수 있습니다. 이는 장기적으로 개발 비용을 절감하고, 개발팀의 자신감을 높이며, 최종적으로는 사용자 만족도를 극대화하는 결과를 가져옵니다.

여러분의 프로젝트에 Playwright를 도입함으로써, 더욱 견고하고 안정적인 웹 애플리케이션을 구축하는 데 한 걸음 더 나아가시기를 강력히 권장합니다. 지금 바로 Playwright를 시작하여 여러분의 웹 애플리케이션 개발 프로세스를 한 단계 업그레이드해 보세요.

Playwright를 사용해 본 경험이나 이 가이드에 대한 의견이 있다면 댓글로 자유롭게 공유해주세요. 여러분의 소중한 피드백은 다른 개발자들에게 큰 도움이 될 것입니다.

📌 함께 읽으면 좋은 글

  • [튜토리얼] Playwright를 활용한 웹 E2E 테스트 자동화 환경 완벽 구축 가이드
  • [개발 책 리뷰] 프로그래머 커리어 로드맵: 실용주의 개발자를 위한 핵심 원칙 탐구
  • [튜토리얼] Nx 워크스페이스 모노레포 프로젝트 설정 및 효율적 관리 가이드

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

반응형