튜토리얼

Playwright로 웹 애플리케이션 E2E 테스트 환경 구축 및 자동화 가이드

강코의 코딩 일기 2026. 4. 27. 16:29
반응형

Playwright를 활용하여 웹 애플리케이션의 E2E 테스트 환경을 구축하고, 안정적인 테스트 자동화를 구현하는 실용적인 가이드입니다. 초기 설정부터 고급 기능까지, 실제 개발에 바로 적용할 수 있는 노하우를 공유합니다.

📑 목차

Playwright로 웹 애플리케이션 E2E 테스트 환경 구축 및 자동화 가이드 - 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

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

웹 애플리케이션의 복잡성은 꾸준히 증가하고 있습니다. 사용자는 다양한 기기와 브라우저 환경에서 끊임없이 새로운 기능을 요구하며, 개발팀은 이러한 요구사항을 충족시키기 위해 빠르게 코드를 배포해야 합니다. 이러한 환경에서 수동 테스트에만 의존하는 것은 여러 가지 문제점을 야기합니다.

  • 시간 소모: 새로운 기능이 추가될 때마다 전체 애플리케이션을 수동으로 테스트하는 것은 엄청난 시간과 인력 소모를 동반합니다.
  • 휴먼 에러: 반복적인 수동 테스트 과정에서 실수가 발생할 가능성이 높으며, 이는 중요한 버그를 놓치는 결과로 이어질 수 있습니다.
  • 일관성 부족: 여러 테스터가 각기 다른 방식으로 테스트를 진행하면, 테스트 결과의 일관성을 보장하기 어렵습니다.
  • 배포 지연: 테스트 병목 현상으로 인해 배포 주기가 길어지고, 이는 시장 변화에 대한 대응력을 약화시킵니다.

이러한 문제들을 해결하기 위한 핵심적인 방법 중 하나가 바로 E2E(End-to-End) 테스트 자동화입니다. E2E 테스트는 실제 사용자의 관점에서 애플리케이션의 모든 흐름을 검증하여, 사용자 경험과 직결되는 잠재적인 문제를 미리 발견하고 해결하는 데 도움을 줍니다. 그리고 이 과정을 자동화함으로써 개발 생산성을 크게 향상시킬 수 있습니다.

수많은 자동화 도구 중에서, 최근 개발자들 사이에서 큰 주목을 받고 있는 것이 바로 Playwright입니다. Playwright는 여러 브라우저와 플랫폼에서 안정적이고 빠르게 웹 애플리케이션을 테스트할 수 있는 강력한 기능을 제공하며, 개발 친화적인 API를 통해 E2E 테스트 환경 구축을 매우 쉽게 만들어줍니다. 이제 Playwright를 활용한 웹 애플리케이션 E2E 테스트 환경 구축 및 자동화 방법을 자세히 알아보겠습니다.

Playwright란 무엇이며, 왜 선택해야 하는가?

Playwright는 Microsoft에서 개발한 Node.js 기반의 오픈 소스 자동화 라이브러리입니다. Chromium (Google Chrome, Microsoft Edge), Firefox, WebKit (Apple Safari) 등 주요 웹 브라우저를 하나의 API로 제어할 수 있어, 진정한 크로스 브라우저 테스트를 가능하게 합니다. 이는 특정 브라우저에서만 발생하는 문제를 효과적으로 찾아내는 데 매우 중요합니다.

Playwright의 핵심 강점

Playwright는 다른 테스트 자동화 도구들과 비교했을 때 다음과 같은 독보적인 강점들을 가지고 있습니다.

  1. 멀티 브라우저 및 플랫폼 지원: Playwright는 Windows, macOS, Linux 환경에서 Chromium, Firefox, WebKit을 모두 지원합니다. 이를 통해 다양한 사용자 환경에서의 호환성 문제를 효과적으로 검증할 수 있습니다.
  2. 자동 대기 (Auto-waiting): Playwright는 요소가 나타나거나 사라지기를 기다리는 등, 비동기적인 웹 환경에 최적화된 자동 대기 기능을 내장하고 있습니다. 덕분에 수동으로 대기 시간을 설정할 필요가 줄어들어 테스트 코드가 더 안정적이고 예측 가능해집니다.
  3. 강력한 디버깅 도구: 테스트 실행 중 스크린샷, 비디오 녹화, 트레이싱(Tracing) 등 다양한 디버깅 기능을 제공하여 테스트 실패 원인을 파악하는 데 매우 유용합니다. 특히 Playwright Inspector는 테스트 코드 생성 및 디버깅을 시각적으로 지원합니다.
  4. 병렬 테스트 실행: Playwright는 여러 테스트를 동시에 병렬로 실행할 수 있는 기능을 내장하고 있어, 대규모 테스트 스위트의 실행 시간을 크게 단축시킬 수 있습니다.
  5. 개발자 친화적인 API: 간결하고 직관적인 API를 제공하여 테스트 코드를 작성하기 쉽습니다. TypeScript를 기본적으로 지원하여 타입 안정성 높은 코드 작성이 가능합니다.
  6. 코드 생성기 (Codegen): 웹 애플리케이션에서 사용자의 동작을 기록하여 자동으로 Playwright 테스트 코드를 생성해주는 기능을 제공합니다. 이는 테스트 작성 초기 단계에서 엄청난 생산성 향상을 가져옵니다.

경쟁 도구(Selenium, Cypress)와의 비교

Playwright를 이해하는 데 도움이 되도록, 널리 사용되는 다른 E2E 테스트 도구인 Selenium 및 Cypress와 비교해보겠습니다.

특징 Playwright Cypress Selenium WebDriver
지원 브라우저 Chromium, Firefox, WebKit (모두 지원) Chromium 기반, Firefox (제한적), Electron 모든 주요 브라우저 (드라이버 필요)
언어 지원 JavaScript/TypeScript, Python, Java, .NET JavaScript/TypeScript 다양한 언어 (Java, Python, C#, Ruby, JS 등)
아키텍처 Node.js 기반, 브라우저와 직접 통신 브라우저 내에서 실행 WebDriver 프로토콜 통해 통신 (드라이버 필요)
자동 대기 내장된 강력한 자동 대기 내장된 자동 대기 수동 대기 설정 필요 (Explicit/Implicit waits)
병렬 실행 기본 지원 및 효율적 플러그인을 통해 제한적 지원 테스트 러너를 통해 구현
디버깅 Inspector, Tracing, 스크린샷, 비디오 타임 트래블, 스냅샷, 개발자 도구 통합 개발자 도구, 로그 분석

Playwright는 최신 웹 기술에 최적화된 아키텍처와 강력한 기능을 바탕으로, 안정적이고 빠른 E2E 테스트 자동화를 구현하는 데 매우 효과적인 선택지입니다.

Playwright 개발 환경 구축하기

이제 본격적으로 Playwright E2E 테스트 환경을 구축해보겠습니다. Node.js 환경에서 진행됩니다.

1. Node.js 및 npm 설치 확인

Playwright는 Node.js 환경에서 실행되므로, 먼저 시스템에 Node.js와 npm(Node Package Manager)이 설치되어 있는지 확인해야 합니다. 터미널 또는 명령 프롬프트에서 다음 명령어를 실행합니다.

node -v
npm -v

만약 설치되어 있지 않다면, Node.js 공식 웹사이트에서 최신 LTS 버전을 다운로드하여 설치해주세요.

2. 새로운 프로젝트 초기화 및 Playwright 설치

테스트 코드를 작성할 새로운 디렉토리를 만들고, 해당 디렉토리로 이동하여 npm 프로젝트를 초기화합니다. 이후 Playwright를 설치합니다.

mkdir playwright-e2e-project
cd playwright-e2e-project
npm init -y

프로젝트 초기화 후, Playwright 테스트 패키지를 설치합니다. 이 명령어는 Playwright 라이브러리뿐만 아니라 테스트에 필요한 Chromium, Firefox, WebKit 브라우저 바이너리도 함께 다운로드합니다.

npm install -D @playwright/test

또는, Playwright 프로젝트를 빠르게 시작하기 위한 초기화 명령어를 사용할 수도 있습니다. 이 명령어는 Playwright 설정 파일, 기본 테스트 예시, 그리고 브라우저를 한 번에 설치해줍니다.

npm init playwright@latest

이 명령어를 실행하면 몇 가지 질문이 나옵니다.

  • Do you want to use TypeScript or JavaScript? (TypeScript 선택 권장)
  • Where to put your end-to-end tests? (기본값인 tests/ 유지)
  • Add a GitHub Actions workflow? (CI/CD 연동 시 Yes, 아니면 No)
  • Install Playwright browsers (chromium, firefox, webkit)? (Yes)

설치가 완료되면 package.json 파일에 Playwright 관련 의존성이 추가되고, playwright.config.ts (또는 .js) 파일과 tests 디렉토리가 생성됩니다.

3. 기본 파일 구조 이해하기

npm init playwright@latest 명령어로 생성된 기본 프로젝트 구조는 다음과 같습니다.

  • package.json: 프로젝트의 메타데이터와 의존성, 스크립트를 정의합니다.
  • playwright.config.ts: Playwright 테스트 러너의 전역 설정을 정의합니다. (예: 브라우저, 기본 URL, 테스트 타임아웃 등)
  • tests/: E2E 테스트 파일들이 위치하는 디렉토리입니다. 각 테스트 파일은 일반적으로 .spec.ts 또는 .spec.js 확장자를 가집니다.
  • tests-examples/: Playwright에서 제공하는 예시 테스트 파일들입니다. 참고용으로 활용하면 좋습니다.

playwright.config.ts 파일의 주요 설정들은 다음과 같습니다.

// 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: {
    trace: 'on-first-retry', // 테스트 실패 시 트레이싱 정보 기록
    baseURL: 'http://localhost:3000', // 테스트할 웹 애플리케이션의 기본 URL
  },

  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
    {
      name: 'firefox',
      use: { ...devices['Desktop Firefox'] },
    },
    {
      name: 'webkit',
      use: { ...devices['Desktop Safari'] },
    },
  ],
});

여기서 baseURL은 테스트할 웹 애플리케이션의 주소를 설정하는 것이 중요하며, projects는 어떤 브라우저에서 테스트를 실행할지 정의합니다. 기본적으로 Chromium, Firefox, WebKit이 설정되어 있습니다.

Playwright로 웹 애플리케이션 E2E 테스트 환경 구축 및 자동화 가이드 - 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

첫 E2E 테스트 작성 및 실행

이제 실제로 간단한 E2E 테스트 시나리오를 작성하고 실행해보겠습니다. 가상의 로그인 페이지를 테스트하는 시나리오를 예로 들어보겠습니다.

  • 사용자가 로그인 페이지에 접속한다.
  • 사용자 이름과 비밀번호를 입력한다.
  • 로그인 버튼을 클릭한다.
  • 로그인 성공 메시지를 확인한다.

1. 테스트 코드 작성하기

tests/ 디렉토리에 login.spec.ts 파일을 생성하고 다음 코드를 작성합니다.

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

// 테스트 그룹 정의
test.describe('로그인 기능 테스트', () => {

  // 각 테스트 실행 전에 특정 URL로 이동하는 훅
  test.beforeEach(async ({ page }) => {
    // 실제 애플리케이션의 로그인 페이지 URL로 변경해야 합니다.
    await page.goto('/login'); // baseURL이 설정되어 있다면 상대 경로 사용 가능
  });

  test('유효한 자격 증명으로 로그인 성공', async ({ page }) => {
    // 1. 사용자 이름 입력 필드에 값 채우기
    await page.fill('input[name="username"]', 'testuser');
    expect(await page.inputValue('input[name="username"]')).toBe('testuser'); // 입력값 확인

    // 2. 비밀번호 입력 필드에 값 채우기
    await page.fill('input[name="password"]', 'password123');
    expect(await page.inputValue('input[name="password"]')).toBe('password123'); // 입력값 확인

    // 3. 로그인 버튼 클릭
    await page.click('button[type="submit"]');

    // 4. 로그인 성공 메시지 또는 리다이렉션 확인
    // 예: "Welcome, testuser!" 텍스트가 보이는지 확인
    await expect(page.locator('text="Welcome, testuser!"')).toBeVisible();

    // 또는, 로그인 성공 후 대시보드 페이지로 이동했는지 URL 확인
    // await expect(page).toHaveURL('/dashboard');
  });

  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('text="Invalid credentials"')).toBeVisible();
  });

});

위 코드에서 page 객체는 현재 브라우저 탭을 나타내며, 이를 통해 페이지 이동, 요소 찾기, 입력, 클릭 등 다양한 상호작용을 수행할 수 있습니다. expect는 테스트 검증을 위한 어설션(assertion) 함수를 제공합니다.

핵심 API 설명:

  • page.goto(url): 지정된 URL로 이동합니다.
  • page.locator(selector): CSS 선택자 또는 텍스트 등을 사용하여 웹 페이지의 요소를 찾습니다.
  • locator.fill(value): 입력 필드에 값을 채웁니다.
  • locator.click(): 요소를 클릭합니다.
  • expect(locator).toBeVisible(): 요소가 화면에 보이는지 확인합니다.
  • expect(page).toHaveURL(url): 현재 페이지의 URL이 특정 URL과 일치하는지 확인합니다.
  • expect(locator).toHaveText(text): 요소의 텍스트 내용이 특정 텍스트와 일치하는지 확인합니다.

2. 테스트 실행하기

터미널에서 다음 명령어를 실행하여 테스트를 실행할 수 있습니다.

npx playwright test

이 명령어는 playwright.config.ts에 정의된 모든 브라우저(Chromium, Firefox, WebKit)에서 tests/ 디렉토리 내의 모든 테스트 파일을 실행합니다. 특정 브라우저에서만 실행하고 싶다면:

npx playwright test --project=chromium

특정 테스트 파일만 실행하고 싶다면:

npx playwright test tests/login.spec.ts

Headless 모드(UI 없이 백그라운드에서 실행)가 아닌 실제 브라우저 UI를 보면서 테스트를 실행하고 싶다면 --headed 옵션을 추가합니다.

npx playwright test --headed

3. 테스트 결과 확인 및 HTML 리포터 활용

테스트 실행이 완료되면, 기본적으로 터미널에 테스트 결과가 출력됩니다. 또한, playwright.config.tsreporter: 'html'이 설정되어 있다면, playwright-report/ 디렉토리에 상세한 HTML 리포트가 생성됩니다.

이 리포트를 열어보려면 다음 명령어를 사용합니다.

npx playwright show-report

HTML 리포트는 각 테스트의 성공/실패 여부, 실행 시간, 로그, 그리고 실패한 경우 스크린샷과 비디오(설정 시)를 포함하여 테스트 결과를 시각적으로 분석하는 데 매우 유용합니다.

Playwright 고급 기능으로 테스트 효율 높이기

Playwright는 단순히 웹 페이지를 클릭하고 입력하는 것을 넘어, E2E 테스트의 효율성과 유지보수성을 극대화할 수 있는 다양한 고급 기능을 제공합니다.

1. 테스트 픽스처와 페이지 객체 모델 (POM)

테스트 코드가 복잡해지고 많아질수록, 코드의 재사용성과 유지보수성은 매우 중요해집니다. 이를 위해 페이지 객체 모델(Page Object Model, POM) 패턴을 적용하고, Playwright의 테스트 픽스처(Test Fixtures)를 활용할 수 있습니다.

페이지 객체 모델 (POM)

POM은 웹 페이지의 UI 요소를 객체로 추상화하여 테스트 코드와 UI 요소를 분리하는 디자인 패턴입니다. 각 웹 페이지(또는 페이지의 특정 컴포넌트)에 해당하는 클래스를 만들고, 해당 페이지에서 수행할 수 있는 동작(메서드)과 UI 요소(셀렉터)를 정의합니다.

POM 적용 예시:

pages/LoginPage.ts

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

export class LoginPage {
  readonly page: Page;
  readonly usernameInput: string = 'input[name="username"]';
  readonly passwordInput: string = 'input[name="password"]';
  readonly loginButton: string = 'button[type="submit"]';
  readonly errorMessage: string = 'text="Invalid credentials"';
  readonly successMessage: string = 'text="Welcome, testuser!"';

  constructor(page: Page) {
    this.page = page;
  }

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

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

  async expectLoginSuccess() {
    await expect(this.page.locator(this.successMessage)).toBeVisible();
  }

  async expectLoginFailure() {
    await expect(this.page.locator(this.errorMessage)).toBeVisible();
  }
}

tests/login.spec.ts (POM 적용)

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

test.describe('로그인 기능 테스트 with POM', () => {

  test('유효한 자격 증명으로 로그인 성공', async ({ page }) => {
    const loginPage = new LoginPage(page);
    await loginPage.goto();
    await loginPage.login('testuser', 'password123');
    await loginPage.expectLoginSuccess();
  });

  test('잘못된 비밀번호로 로그인 실패', async ({ page }) => {
    const loginPage = new LoginPage(page);
    await loginPage.goto();
    await loginPage.login('testuser', 'wrongpassword');
    await loginPage.expectLoginFailure();
  });

});

이렇게 하면 테스트 코드는 페이지의 내부 구현 상세를 알 필요 없이, 페이지 객체의 메서드를 호출하여 테스트를 수행할 수 있게 됩니다. UI 변경이 발생하더라도 LoginPage 클래스만 수정하면 되므로, 테스트 코드의 유지보수성이 크게 향상됩니다.

테스트 픽스처 (Test Fixtures)

Playwright는 기본적으로 page, browser, context와 같은 내장 픽스처를 제공합니다. 개발자는 커스텀 픽스처를 정의하여 테스트 간에 공유되는 객체나 설정을 관리할 수 있습니다. 예를 들어, 로그인된 사용자 상태를 공유하는 픽스처를 만들 수 있습니다.

// playwright.config.ts 또는 별도 파일
import { test as base } from '@playwright/test';
import { LoginPage } from './pages/LoginPage'; // LoginPage 임포트

type MyFixtures = {
  loginPage: LoginPage;
  loggedInPage: LoginPage; // 로그인된 페이지 픽스처
};

export const test = base.extend({
  loginPage: async ({ page }, use) => {
    const loginPage = new LoginPage(page);
    await use(loginPage);
  },

  loggedInPage: async ({ page, loginPage }, use) => {
    // loginPage 픽스처를 재사용하여 로그인 상태를 만듦
    await loginPage.goto();
    await loginPage.login('testuser', 'password123');
    await loginPage.expectLoginSuccess(); // 로그인 성공 확인
    await use(loginPage); // 로그인된 페이지를 테스트에 제공
  },
});

tests/dashboard.spec.ts (로그인된 페이지 픽스처 사용)

// tests/dashboard.spec.ts
import { test, expect } from '../playwright.config'; // 커스텀 테스트 임포트

test.describe('대시보드 기능 테스트', () => {
  test('로그인 후 대시보드 페이지에 접근 가능', async ({ loggedInPage }) => {
    // 이미 loggedInPage 픽스처를 통해 로그인된 상태로 시작
    await expect(loggedInPage.page).toHaveURL('/dashboard');
    await expect(loggedInPage.page.locator('h1')).toHaveText('Dashboard');
  });

  // 다른 대시보드 관련 테스트들...
});

이렇게 픽스처를 사용하면 각 테스트마다 로그인 과정을 반복해서 작성할 필요 없이, 미리 정의된 로그인 상태에서 테스트를 시작할 수 있어 테스트 작성 시간 단축코드 중복 제거에 매우 효과적입니다.

2. 시나리오별 데이터 관리 (Test Data Management)

E2E 테스트는 다양한 시나리오를 커버해야 하며, 각 시나리오마다 다른 테스트 데이터가 필요할 수 있습니다. 테스트 데이터를 코드 내에 하드코딩하면, 데이터 변경 시마다 코드를 수정해야 하는 번거로움이 있습니다. 따라서 테스트 데이터를 외부에서 관리하는 것이 좋습니다.

  • JSON 파일 활용: 사용자 정보, 상품 정보 등 다양한 테스트 데이터를 JSON 파일로 분리하여 관리할 수 있습니다.
  • 환경 변수: 민감한 정보(예: API 키)는 환경 변수를 통해 주입받아 사용합니다.
  • 데이터베이스 시딩(Seeding): 테스트 시작 전에 필요한 데이터를 데이터베이스에 미리 삽입하고, 테스트 완료 후 정리하는 방법을 사용합니다.

JSON 파일 데이터 예시:

test-data/users.json

// test-data/users.json
{
  "validUser": {
    "username": "testuser",
    "password": "password123"
  },
  "invalidUser": {
    "username": "unknown",
    "password": "wrongpassword"
  }
}

tests/login.spec.ts (JSON 데이터 사용)

// tests/login.spec.ts
import { test, expect } from '@playwright/test';
import { LoginPage } from '../pages/LoginPage';
import * as testData from '../test-data/users.json'; // JSON 데이터 임포트

test.describe('로그인 기능 테스트 with Data', () => {

  test('유효한 자격 증명으로 로그인 성공', async ({ page }) => {
    const loginPage = new LoginPage(page);
    await loginPage.goto();
    await loginPage.login(testData.validUser.username, testData.validUser.password);
    await loginPage.expectLoginSuccess();
  });

  test('잘못된 비밀번호로 로그인 실패', async ({ page }) => {
    const loginPage = new LoginPage(page);
    await loginPage.goto();
    await loginPage.login(testData.invalidUser.username, testData.invalidUser.password);
    await loginPage.expectLoginFailure();
  });

});

이처럼 데이터를 분리하여 관리하면, 테스트 시나리오를 변경하지 않고도 다양한 데이터 조합으로 테스트를 실행할 수 있어 테스트 커버리지를 효과적으로 확장할 수 있습니다.

3. 스크린샷 및 비디오 레코딩

테스트가 실패했을 때, 실패 당시의 화면 상태를 확인하는 것은 디버깅에 매우 중요합니다. Playwright는 테스트 실패 시 자동으로 스크린샷을 찍거나, 테스트 전체 과정을 비디오로 녹화하는 기능을 제공합니다.

playwright.config.ts 파일에서 이 기능을 설정할 수 있습니다.

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

export default defineConfig({
  // ...다른 설정들...

  use: {
    // 테스트 실패 시 스크린샷 저장
    screenshot: 'only-on-failure', // 'on', 'off', 'only-on-failure'
    // 테스트 실패 시 비디오 녹화
    video: 'on-first-retry', // 'on', 'off', 'retain-on-failure', 'on-first-retry'
    // 테스트 트레이싱 정보 기록 (디버깅 도구)
    trace: 'on-first-retry', // 'on', 'off', 'retain-on-failure', 'on-first-retry'
  },

  // ...
});
  • screenshot: 'only-on-failure'로 설정하면 테스트가 실패했을 때만 스크린샷을 저장합니다.
  • video: 'on-first-retry'로 설정하면 첫 번째 테스트 실패 시 비디오를 녹화합니다. 'retain-on-failure'는 실패한 테스트의 비디오를 항상 보관합니다.
  • trace: Playwright의 강력한 트레이싱 기능은 테스트 실행의 모든 단계를 기록하여, 실패 원인을 시각적으로 분석할 수 있게 돕습니다.

이러한 설정들은 테스트가 실패했을 때 빠르게 원인을 파악하고 수정하는 데 결정적인 도움을 줍니다. HTML 리포트에서 이 결과들을 쉽게 확인할 수 있습니다.

Playwright로 웹 애플리케이션 E2E 테스트 환경 구축 및 자동화 가이드 - 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

CI/CD 파이프라인에 Playwright 통합하기

E2E 테스트의 진정한 가치는 CI/CD(지속적 통합/지속적 배포) 파이프라인에 통합될 때 발휘됩니다. 코드 변경이 발생할 때마다 자동으로 E2E 테스트가 실행되어 회귀(regression) 버그를 조기에 발견하고, 안정적인 배포를 보장합니다.

1. CI/CD 통합의 중요성

  • 조기 버그 발견: 개발 초기 단계에서 버그를 발견하여 수정 비용을 최소화합니다.
  • 코드 품질 향상: 모든 코드 변경이 테스트를 통과해야 하므로 코드 품질에 대한 신뢰도가 높아집니다.
  • 안정적인 배포: 테스트를 통과한 코드만 배포되도록 하여 프로덕션 환경에서의 오류 가능성을 줄입니다.
  • 개발 생산성 증대: 수동 테스트에 드는 시간을 절약하고, 개발자는 더 중요한 기능 개발에 집중할 수 있습니다.

2. GitHub Actions를 이용한 통합 예시

가장 널리 사용되는 CI/CD 도구 중 하나인 GitHub Actions를 사용하여 Playwright E2E 테스트를 자동화하는 워크플로우를 설정하는 방법을 살펴보겠습니다.

프로젝트 루트 디렉토리에 .github/workflows/ 폴더를 생성하고, 그 안에 playwright.yml 파일을 생성합니다.

# .github/workflows/playwright.yml
name: Playwright Tests

on:
  push:
    branches: [ main, master ]
  pull_request:
    branches: [ main, master ]

jobs:
  test:
    timeout-minutes: 60
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: actions/setup-node@v4
      with:
        node-version: 18

    - name: Install dependencies
      run: npm ci

    - name: Install Playwright browsers
      run: npx playwright install --with-deps

    - name: Start your application (if needed)
      run: npm start & # 백그라운드에서 웹 애플리케이션 실행
      # 애플리케이션의 실제 시작 스크립트에 맞게 수정하세요.
      # 예를 들어, React 앱은 `npm start`, Node.js 서버는 `node server.js` 등
      # `playwright.config.ts`의 `baseURL`과 일치하는 포트에서 실행되어야 합니다.

    - name: Run Playwright tests
      run: npx playwright test

    - uses: actions/upload-artifact@v4
      if: always()
      with:
        name: playwright-report
        path: playwright-report/
        retention-days: 30

워크플로우 설명:

  • on: main 또는 master 브랜치에 push 또는 pull_request 이벤트가 발생했을 때 워크플로우를 실행합니다.
  • jobs.test.runs-on: Ubuntu 최신 버전 환경에서 작업을 실행합니다.
  • actions/checkout@v4: 레포지토리 코드를 워크플로우 환경으로 체크아웃합니다.
  • actions/setup-node@v4: Node.js 환경을 설정합니다.
  • npm ci: package-lock.json에 기반하여 의존성을 설치합니다.
  • npx playwright install --with-deps: Playwright 브라우저와 필요한 시스템 의존성을 설치합니다. --with-deps는 Xvfb 같은 그래픽 라이브러리를 함께 설치하여 Headless 모드에서도 안정적으로 동작하게 합니다.
  • npm start &: 테스트할 웹 애플리케이션을 백그라운드에서 실행합니다. 이 부분이 중요하며, 실제 프로젝트에 맞게 수정해야 합니다. playwright.config.ts에 설정된 baseURL에 맞게 애플리케이션이 실행되어야 합니다.
  • npx playwright test: Playwright E2E 테스트를 실행합니다.
  • actions/upload-artifact@v4: 테스트가 완료된 후 생성된 playwright-report/ 디렉토리를 아티팩트로 업로드합니다. 이를 통해 CI/CD 대시보드에서 테스트 결과를 다운로드하여 확인할 수 있습니다. if: always()는 테스트 성공 여부와 관계없이 항상 아티팩트를 업로드하도록 합니다.

3. CI 환경 설정 시 고려사항

  • Headless 모드: CI 환경에서는 일반적으로 브라우저 UI 없이 Headless 모드로 테스트를 실행합니다. Playwright는 기본적으로 Headless 모드입니다.
  • 환경 변수: CI 환경에서만 필요한 특정 설정(예: 테스트 서버 URL, API 키)은 환경 변수로 주입하여 사용합니다.
  • 병렬 테스트 실행: 대규모 테스트 스위트는 실행 시간이 길어질 수 있습니다. Playwright는 --shard 옵션을 통해 테스트를 여러 부분으로 나누어 병렬로 실행할 수 있습니다. 예를 들어, 3개의 워커에서 테스트를 분산 실행하려면 npx playwright test --shard=1/3, --shard=2/3, --shard=3/3와 같이 설정할 수 있습니다. GitHub Actions의 matrix 기능을 활용하면 효과적으로 병렬 처리를 구현할 수 있습니다.
  • 리소스 관리: CI 환경의 리소스(CPU, 메모리)는 제한적일 수 있으므로, 테스트가 너무 많은 리소스를 사용하지 않도록 주의해야 합니다. 불필요한 테스트를 제거하거나, 테스트 데이터를 최적화하는 등의 노력이 필요합니다.

이렇게 CI/CD 파이프라인에 Playwright E2E 테스트를 통합함으로써, 개발팀은 더 높은 신뢰도를 가지고 빠르게 기능을 개발하고 배포할 수 있습니다.

마무리하며: 안정적인 웹 서비스를 위한 E2E 테스트 자동화

지금까지 Playwright를 활용하여 웹 애플리케이션 E2E 테스트 환경을 구축하고, 실제 테스트를 작성 및 실행하며, 나아가 고급 기능과 CI/CD 통합까지 살펴보았습니다. Playwright는 그 강력한 기능과 개발 친화적인 API 덕분에 E2E 테스트 자동화 분야에서 매우 강력한 도구로 자리매김하고 있습니다.

E2E 테스트 자동화는 단순히 버그를 찾는 것을 넘어, 개발 프로세스의 효율성을 높이고, 제품의 품질을 보장하며, 최종적으로 사용자에게 더 나은 경험을 제공하는 핵심적인 과정입니다. Playwright는 멀티 브라우저 지원, 자동 대기, 강력한 디버깅 도구, 그리고 쉬운 CI/CD 통합을 통해 이러한 목표를 달성하는 데 큰 도움을 줄 것입니다.

이 가이드에서 제시된 내용을 바탕으로 여러분의 웹 애플리케이션에 Playwright E2E 테스트를 도입하고, 더욱 안정적이고 신뢰성 있는 서비스를 구축하시길 바랍니다. 테스트 자동화는 한 번의 설정으로 끝나는 것이 아니라, 애플리케이션의 변화에 맞춰 꾸준히 관리하고 발전시켜야 하는 지속적인 노력임을 기억해주세요.

혹시 Playwright를 사용하면서 겪었던 경험이나 궁금한 점이 있으시다면, 아래 댓글로 자유롭게 공유해주세요! 함께 더 나은 테스트 환경을 만들어나갈 수 있습니다.

📌 함께 읽으면 좋은 글

  • [튜토리얼] Next.js 프로젝트에 TypeScript, ESLint, Prettier 완벽 설정 가이드
  • [생산성 자동화] Makefile 활용: 개발 워크플로우를 자동화하고 생산성을 극대화하는 비법
  • [튜토리얼] Prometheus Grafana 실시간 모니터링 시스템 구축 가이드

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

반응형