Playwright의 확장 기능과 커스터마이징
Playwright에서 page.on()으로 클릭, 입력 등 브라우저 이벤트를 감지해 테스트 코드를 생성할 수 있으며, TypeScript로 안정성을 높일 수 있습니다. 플러그인으로 로그인 자동화 등 기능을 재사용하거나, Supertest와 통합해 API와 UI 데이터를 검증할 수 있습니다. 결과는 JSON, CSV, Markdown, HTML로 저장해 보고서를 생성할 수 있습니다.

커스텀 코드 생성기 작성
Playwright에서 커스텀 코드 생성기를 작성하려면 Playwright의 이벤트 핸들러와 스크립트 캡처 기능을 활용하여 브라우저에서 발생하는 이벤트를 기반으로 코드를 생성할 수 있습니다. 아래는 기본적인 커스텀 코드 생성기의 설계 및 구현 방안을 소개합니다.
1. 목표
- 브라우저에서 사용자가 실행한 동작(클릭, 입력 등)을 기반으로 Playwright 테스트 코드를 자동으로 생성.
- 사용자 정의 포맷으로 코드를 출력하거나 특정 작업을 자동화.
2. 구현 방법
2.1 Playwright 이벤트 기반 코드 생성
Playwright는 page.on()
메서드를 통해 다양한 이벤트(클릭, 네트워크 요청, 입력 등)를 캡처할 수 있습니다. 이를 활용하여 사용자의 행동을 추적하고, 이를 테스트 코드로 변환하는 로직을 작성합니다.
2.2 주요 이벤트 추적
다음은 자주 사용되는 이벤트와 그 처리 방식입니다.
- click: 사용자가 특정 버튼이나 링크를 클릭했을 때.
- type: 사용자가 입력 필드에 텍스트를 입력했을 때.
- navigate: 사용자가 페이지를 이동했을 때.
- network: API 호출, 리소스 로드 등을 추적.
3. 코드 예시
아래는 간단한 Playwright 커스텀 코드 생성기의 구현 예시입니다.
const fs = require('fs');
const { chromium } = require('playwright');
// Playwright 테스트 코드 생성기
(async () => {
// 브라우저 및 페이지 생성
const browser = await chromium.launch({ headless: false });
const context = await browser.newContext();
const page = await context.newPage();
// 생성된 코드를 저장할 배열
let recordedSteps = [];
// 이벤트 리스너 설정
page.on('click', async (event) => {
const selector = await event.target.selector();
recordedSteps.push(`await page.click('${selector}');`);
});
page.on('input', async (event) => {
const value = event.target.value;
const selector = await event.target.selector();
recordedSteps.push(`await page.fill('${selector}', '${value}');`);
});
page.on('navigation', (request) => {
recordedSteps.push(`await page.goto('${request.url()}');`);
});
// 사용자가 실행한 동작을 기반으로 코드 작성
page.on('close', () => {
const outputCode = `
const { test } = require('@playwright/test');
test('Generated Test', async ({ page }) => {
${recordedSteps.join('\n')}
});
`;
// 생성된 코드를 파일로 저장
fs.writeFileSync('generated-test.js', outputCode, 'utf-8');
console.log('Generated test code saved to generated-test.js');
});
// URL로 이동
await page.goto('https://example.com');
// 테스트 환경을 위해 브라우저 유지
await new Promise(resolve => setTimeout(resolve, 300000));
await browser.close();
})();
4. 설명
- 이벤트 캡처
page.on('click')
: 사용자가 클릭한 요소를 캡처하여 Playwright의page.click()
코드로 변환.page.on('input')
: 입력한 텍스트를 추적하여 Playwright의page.fill()
코드로 변환.page.on('navigation')
: 페이지 이동을 추적하여page.goto()
코드로 변환.
- 코드 저장
- 사용자가 실행한 동작을 기록한 배열(
recordedSteps
)에 동작을 추가. - 페이지가 닫히는 시점에 전체 동작을 테스트 코드로 변환하여 파일로 저장.
- 사용자가 실행한 동작을 기록한 배열(
- 파일 저장
- 생성된 코드를
generated-test.js
파일에 저장하여 나중에 실행 가능.
- 생성된 코드를
5. 확장 가능성
- 다양한 이벤트 추가
page.on('dialog')
: 경고창, 확인창 등의 동작 기록.page.on('response')
: 네트워크 응답 추적.
- UI 강화
- GUI 기반으로 이벤트를 실시간으로 시각화.
- 코드 포맷 옵션 추가
- 예: TypeScript, 특정 프레임워크(예: Jest) 코드 스타일.
위 코드는 기본적인 커스텀 코드 생성기의 시작점으로, 필요한 기능에 따라 확장할 수 있습니다.
아래는 Playwright 커스텀 코드 생성기를 TypeScript로 작성한 예시 코드입니다. TypeScript의 타입 시스템을 활용하여 더 안전한 코드를 작성할 수 있도록 구성했습니다.
import { chromium, Page } from 'playwright';
import * as fs from 'fs';
// Playwright 테스트 코드 생성기
(async () => {
// 브라우저 및 페이지 생성
const browser = await chromium.launch({ headless: false });
const context = await browser.newContext();
const page = await context.newPage();
// 생성된 코드를 저장할 배열
const recordedSteps: string[] = [];
// 유틸리티 함수: CSS 셀렉터 가져오기
const getSelector = async (page: Page, elementHandle: any): Promise<string> => {
const selector = await page.evaluate((el) => {
const path: string[] = [];
while (el && el.nodeType === Node.ELEMENT_NODE) {
let selector = el.nodeName.toLowerCase();
if (el.id) {
selector += `#${el.id}`;
} else if (el.className) {
selector += `.${el.className.split(' ').join('.')}`;
}
path.unshift(selector);
el = el.parentElement;
}
return path.join(' > ');
}, elementHandle);
return selector;
};
// 이벤트 리스너 설정
page.on('click', async (event) => {
const elementHandle = event.target();
if (elementHandle) {
const selector = await getSelector(page, elementHandle);
recordedSteps.push(`await page.click('${selector}');`);
}
});
page.on('input', async (event) => {
const elementHandle = event.target();
if (elementHandle) {
const selector = await getSelector(page, elementHandle);
const value = await page.evaluate((el) => (el as HTMLInputElement).value, elementHandle);
recordedSteps.push(`await page.fill('${selector}', '${value}');`);
}
});
page.on('framenavigated', (frame) => {
if (frame.url() !== 'about:blank') {
recordedSteps.push(`await page.goto('${frame.url()}');`);
}
});
// 페이지 닫힐 때 생성된 코드를 저장
page.on('close', () => {
const outputCode = `
import { test, expect } from '@playwright/test';
test('Generated Test', async ({ page }) => {
${recordedSteps.join('\n ')}
});
`;
// 파일로 저장
fs.writeFileSync('generated-test.ts', outputCode, 'utf-8');
console.log('Generated test code saved to generated-test.ts');
});
// URL로 이동
await page.goto('https://example.com');
// 테스트 환경을 위해 브라우저 유지
console.log('Recording actions... Perform your actions in the browser.');
await new Promise((resolve) => setTimeout(resolve, 300000)); // 5분 대기
await browser.close();
})();
주요 변경점 및 설명
- TypeScript 사용
import
구문으로 TypeScript 모듈 가져오기.Page
및chromium
등 Playwright에서 제공하는 타입 명시.- 이벤트 핸들러나 함수에 적절한 타입 추가(
Page
,string
,any
등).
- 유틸리티 함수
getSelector
: 선택자를 계산하여 CSS 셀렉터를 정확히 가져오는 함수. DOM 트리를 거슬러 올라가며 고유 셀렉터를 생성.
- 코드 저장
- 기록된 테스트 코드가 TypeScript 형식으로 출력되며,
@playwright/test
기반의 테스트 구조를 포함.
- 기록된 테스트 코드가 TypeScript 형식으로 출력되며,
- 기본 이벤트 처리
- Click 이벤트:
page.click()
코드로 변환. - Input 이벤트: 입력 필드의 값을 추적하여
page.fill()
코드로 변환. - Navigation 이벤트:
page.goto()
코드로 변환.
- Click 이벤트:
- 타임아웃 설정
- 브라우저를 5분 동안 유지(
setTimeout
)하며 사용자가 필요한 동작을 수행할 수 있도록 구성.
- 브라우저를 5분 동안 유지(
- 파일 저장 경로
- 생성된 코드는
generated-test.ts
라는 이름으로 저장됩니다.
- 생성된 코드는
확장 포인트
- 다양한 이벤트 추가
- 네트워크 요청(
page.on('request')
,page.on('response')
) 추적. - 팝업 및 다이얼로그(
page.on('dialog')
) 처리.
- 네트워크 요청(
- GUI 시각화 추가
- 이벤트를 실시간으로 화면에 보여주는 UI 추가.
- 코드 포맷 옵션
- ESLint나 Prettier를 활용해 출력되는 코드를 포맷팅.
위 코드는 Playwright와 TypeScript를 사용하는 프로젝트에 바로 통합할 수 있습니다.
플러그인 활용하기
Playwright에서 플러그인을 활용하면 코드 재사용성을 높이고 기능을 확장할 수 있습니다. 특히, Playwright Test Fixtures, Custom Plugins, 그리고 Third-party Plugin을 활용하면 테스트 자동화가 더욱 효율적이 됩니다.
1. Playwright 플러그인을 활용하는 이유
- 공통 기능(로그인, API 요청, 성능 측정 등)의 재사용성 증가
- 코드 유지보수 및 가독성 향상
- 테스트 실행 시 로깅(logging), 트레이싱(tracing), 리포팅(reporting) 등의 기능 추가 가능
- 커스텀 Playwright 플러그인을 만들어 특정 기능을 확장 가능
2. 기본적인 Playwright 플러그인 활용 방법
Playwright는 기본적으로 test fixtures 기능을 제공하며, 이를 활용하여 플러그인을 구현할 수 있습니다.
(1) Playwright Test Fixtures를 이용한 플러그인
Playwright에서 제공하는 test.extend()
를 활용하면 테스트 환경을 확장할 수 있습니다.
📌 예제: 사용자 로그인 플러그인
아래는 자동 로그인을 수행하는 Playwright 플러그인을 만드는 예제입니다.
import { test as base } from '@playwright/test';
// 사용자 로그인 플러그인 정의
export const test = base.extend<{ login: () => Promise<void> }>({
login: async ({ page }, use) => {
await page.goto('https://example.com/login');
await page.fill('#username', 'testuser');
await page.fill('#password', 'password123');
await page.click('button[type="submit"]');
await page.waitForNavigation();
await use();
},
});
테스트에서 활용
위에서 정의한 플러그인을 활용하여 로그인한 후 다른 작업을 수행할 수 있습니다.
import { test, expect } from './my-plugin';
test('로그인이 필요한 페이지 테스트', async ({ page, login }) => {
await login(); // 로그인 플러그인 실행
await page.goto('https://example.com/dashboard');
const welcomeMessage = await page.locator('.welcome').textContent();
expect(welcomeMessage).toContain('Welcome, testuser');
});
✅ 장점
- 매 테스트마다 로그인 과정을 반복할 필요 없이
login()
을 호출하여 간단하게 로그인 가능 test.extend()
로 여러 개의 플러그인을 조합하여 활용 가능
3. 커스텀 Playwright 플러그인 만들기
Playwright는 확장성을 고려하여 사용자 정의 플러그인을 지원합니다. 이를 활용하면 Playwright의 기능을 확장할 수 있습니다.
(1) 페이지 내 요소를 추적하는 플러그인
아래 플러그인은 사용자가 상호작용한 요소를 기록하여 코드로 변환하는 기능을 제공합니다.
import { Page } from 'playwright';
export class ActionRecorder {
private steps: string[] = [];
constructor(private page: Page) {}
async startRecording() {
this.page.on('click', async (event) => {
const selector = await event.target().evaluate((el) => el.outerHTML);
this.steps.push(`await page.click('${selector}');`);
});
this.page.on('input', async (event) => {
const selector = await event.target().evaluate((el) => el.outerHTML);
const value = await event.target().evaluate((el) => (el as HTMLInputElement).value);
this.steps.push(`await page.fill('${selector}', '${value}');`);
});
console.log('Recording started...');
}
stopRecording() {
console.log('Recorded steps:');
console.log(this.steps.join('\n'));
}
}
(2) 사용법
import { chromium } from 'playwright';
import { ActionRecorder } from './action-recorder';
(async () => {
const browser = await chromium.launch({ headless: false });
const context = await browser.newContext();
const page = await context.newPage();
const recorder = new ActionRecorder(page);
await recorder.startRecording();
await page.goto('https://example.com');
await page.waitForTimeout(5000); // 사용자 입력 대기
recorder.stopRecording();
await browser.close();
})();
✅ 기능
- 사용자의 클릭 및 입력 기록
stopRecording()
을 호출하면 기록된 테스트 코드 자동 출력- Playwright의 기본 기능을 확장하여 반복적인 테스트 코드 작성 자동화
4. 서드파티(Third-Party) Playwright 플러그인 활용
Playwright는 공식적으로 여러 플러그인을 지원하며, 아래와 같은 기능을 추가할 수 있습니다.
(1) Playwright 공식 플러그인
- @playwright/test: 기본 테스트 프레임워크
- playwright-aws-lambda: AWS Lambda 환경에서 Playwright 실행
- @playwright/experimental-ct-react: React 컴포넌트 테스트 지원
(2) 서드파티 플러그인
- playwright-video: Playwright 테스트 실행을 동영상으로 저장
- playwright-trace-viewer: Playwright 트레이스를 GUI로 확인
📌 예제: Playwright 동영상 녹화 플러그인 활용
Playwright 테스트를 실행하는 동안 동영상을 녹화할 수 있습니다.
import { test as base } from '@playwright/test';
export const test = base.extend({
context: async ({ browser }, use) => {
const context = await browser.newContext({
recordVideo: { dir: 'videos/' },
});
await use(context);
await context.close();
},
});
test('녹화 테스트', async ({ page }) => {
await page.goto('https://example.com');
await page.waitForTimeout(5000); // 5초 대기 (녹화 확인용)
});
✅ 장점
- 테스트 실행 과정을 동영상으로 저장하여 디버깅에 활용 가능
videos/
폴더에 테스트 실행 동영상이 자동 저장됨- Playwright Test Fixtures를 사용하여 로그인, API 호출 등의 반복적인 기능을 플러그인화할 수 있음.
- 커스텀 플러그인을 제작하여 사용자 이벤트 추적, 자동 코드 생성 등의 기능을 확장 가능.
- 서드파티 플러그인을 활용하여 동영상 녹화, 트레이스 뷰어, 클라우드 환경 실행 등의 기능 추가 가능.
📌 Playwright 플러그인은 테스트 자동화를 더욱 강력하게 만들어주며, 확장성이 뛰어납니다. 필요에 따라 맞춤형 플러그인을 제작하거나 기존 플러그인을 활용하면 효율적인 테스트 환경을 구축할 수 있습니다.
Playwright와 외부 라이브러리 통합
Playwright와 외부 라이브러리를 통합하면 테스트 자동화의 기능을 확장하고, 데이터 처리, API 호출, 데이터베이스 연동, 보고서 생성 등 다양한 기능을 추가할 수 있습니다.
1. Playwright와 외부 라이브러리 통합이 필요한 경우
✅ 테스트 데이터 관리: Faker.js, Chance.js를 사용하여 무작위 데이터 생성
✅ API 테스트: Axios, Supertest를 사용하여 API 요청 및 응답 검증
✅ 데이터베이스 연동: MySQL, PostgreSQL, MongoDB 등의 DB에서 데이터를 가져와 테스트
✅ 보고서 생성: Allure, HTML Report를 사용하여 테스트 리포트 생성
✅ 파일 처리: fs (파일 시스템), ExcelJS를 사용하여 데이터 입출력
2. Playwright + API 요청 (Axios, Supertest)
Playwright 테스트 중 API를 호출하여 데이터를 확인하거나, UI 테스트 전에 데이터를 미리 설정할 수 있습니다.
(1) Axios와 Playwright 연동
📌 Axios를 활용하여 API 요청을 보내고, 응답을 검증하는 예제
import { test, expect } from '@playwright/test';
import axios from 'axios';
test('API 응답을 검증한 후 UI 테스트', async ({ page }) => {
const response = await axios.get('https://jsonplaceholder.typicode.com/posts/1');
expect(response.status).toBe(200);
expect(response.data).toHaveProperty('title');
await page.goto('https://example.com');
await expect(page.locator('h1')).toHaveText(response.data.title);
});
✅ API 데이터와 UI 데이터가 일치하는지 확인 가능
✅ Playwright 실행 중 API 요청을 직접 호출하여 API 응답을 UI와 비교 가능
(2) Supertest와 Playwright 연동
📌 Supertest를 활용하여 API 테스트를 Playwright에 통합하는 예제
import { test, expect } from '@playwright/test';
import request from 'supertest';
test('Supertest를 활용한 API 검증', async ({ page }) => {
const api = request('https://jsonplaceholder.typicode.com');
const response = await api.get('/posts/1');
expect(response.status).toBe(200);
expect(response.body.title).toBeDefined();
});
✅ Supertest는 API 테스트에 특화된 라이브러리로, REST API를 쉽게 호출하고 검증 가능
3. Playwright + 무작위 데이터 생성 (Faker.js)
UI 입력 필드 테스트 시 동적 데이터를 사용해야 할 때가 많습니다. Faker.js를 활용하면 가짜 이름, 이메일, 주소 등을 생성하여 테스트할 수 있습니다.
(1) Faker.js로 가짜 데이터 생성
📌 Faker.js를 사용하여 무작위 사용자 데이터를 생성하여 폼을 자동 입력하는 예제
import { test, expect } from '@playwright/test';
import { faker } from '@faker-js/faker';
test('무작위 사용자 데이터 입력', async ({ page }) => {
const name = faker.name.fullName();
const email = faker.internet.email();
const password = faker.internet.password();
await page.goto('https://example.com/signup');
await page.fill('#name', name);
await page.fill('#email', email);
await page.fill('#password', password);
await page.click('button[type="submit"]');
expect(await page.locator('.welcome-message').textContent()).toContain(name);
});
✅ 매번 새로운 테스트 데이터를 생성하여 폼 입력 테스트 수행 가능
✅ 실제 사용자의 데이터를 입력하는 것처럼 테스트 가능
4. Playwright + 데이터베이스 연동 (MySQL, PostgreSQL, MongoDB)
테스트 실행 전후로 데이터베이스에서 데이터를 삽입하거나 검증해야 하는 경우 Playwright와 DB 라이브러리를 통합할 수 있습니다.
(1) MySQL 연동
📌 MySQL에서 데이터를 조회한 후, Playwright UI 테스트에서 검증하는 예제
import { test, expect } from '@playwright/test';
import mysql from 'mysql2/promise';
test('MySQL 데이터를 기반으로 UI 테스트', async ({ page }) => {
const connection = await mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'password',
database: 'testdb',
});
const [rows] = await connection.execute('SELECT name FROM users WHERE id = ?', [1]);
const userName = rows[0]?.name;
await page.goto('https://example.com/user-profile');
expect(await page.locator('.user-name').textContent()).toContain(userName);
await connection.end();
});
✅ DB에서 가져온 데이터를 Playwright 테스트에 활용 가능
✅ UI에 표시된 데이터가 실제 DB와 일치하는지 검증 가능
5. Playwright + 테스트 보고서 생성 (Allure, HTML Report)
Playwright에서 실행된 테스트 결과를 시각적으로 확인할 수 있도록 보고서를 생성할 수 있습니다.
(1) Playwright 기본 HTML Report
Playwright는 기본적으로 --reporter=html
옵션을 제공하여 HTML 형태의 리포트를 생성할 수 있습니다.
npx playwright test --reporter=html
✅ playwright-report/index.html
에서 상세 리포트 확인 가능
(2) Allure Report 연동
📌 Allure를 Playwright에 추가하여 더욱 상세한 보고서를 생성
npm install --save-dev allure-playwright
📌 Playwright 설정 파일(playwright.config.ts
) 수정
import { defineConfig } from '@playwright/test';
export default defineConfig({
reporter: [
['list'],
['allure-playwright'],
],
});
📌 테스트 실행 후 Allure 리포트 생성
npx playwright test
npx allure generate allure-results --clean
npx allure open
✅ 테스트 실행 기록, 오류 로그, 스크린샷 등을 시각적으로 확인 가능
6. Playwright + 파일 처리 (fs, ExcelJS)
UI 테스트 중에 파일을 읽거나 다운로드한 파일을 검증해야 할 때 파일 시스템(fs) 및 ExcelJS를 사용할 수 있습니다.
(1) 파일 다운로드 후 검증
📌 Playwright에서 파일을 다운로드한 후 해당 파일이 존재하는지 확인
import { test, expect } from '@playwright/test';
import * as fs from 'fs';
test('파일 다운로드 후 존재 여부 확인', async ({ page }) => {
await page.goto('https://example.com/download');
const [download] = await Promise.all([
page.waitForEvent('download'),
page.click('a#download-link'),
]);
const filePath = await download.path();
expect(fs.existsSync(filePath!)).toBe(true);
});
✅ Playwright에서 파일 다운로드 후 실제로 존재하는지 검증 가능
(2) ExcelJS를 활용한 데이터 검증
📌 Excel 데이터를 읽고 UI에 표시된 값과 비교
import { test, expect } from '@playwright/test';
import * as ExcelJS from 'exceljs';
test('Excel 데이터를 읽고 UI 검증', async ({ page }) => {
const workbook = new ExcelJS.Workbook();
await workbook.xlsx.readFile('test-data.xlsx');
const worksheet = workbook.getWorksheet(1);
const cellValue = worksheet.getCell('A1').value as string;
await page.goto('https://example.com');
expect(await page.locator('.data-field').textContent()).toBe(cellValue);
});
✅ Excel 데이터와 UI 데이터를 비교하여 정확성 검증 가능
- Playwright와 외부 라이브러리를 결합하여 API, 데이터베이스, 보고서, 파일 처리 등 다양한 기능을 추가할 수 있습니다.
- 테스트 데이터 자동 생성(Faker.js), API 연동(Axios, Supertest), DB 조회(MySQL, PostgreSQL), 보고서 생성(Allure) 등의 기능을 쉽게 통합 가능.
- 이러한 기술들을 조합하면 더욱 강력한 E2E 테스트 환경을 구축할 수 있습니다. 🎯🚀
Supertest와 Playwright 연동 상세 설명
1. Supertest란?
Supertest는 Node.js 기반의 HTTP 요청 테스트 라이브러리로, REST API의 응답을 검증하는 데 사용됩니다.
Playwright와 함께 사용하면 UI 테스트 실행 중 API 요청을 수행하고 API 데이터와 UI 데이터를 비교할 수 있습니다.
✅ 주요 기능
- HTTP 요청 (
GET
,POST
,PUT
,DELETE
) 테스트 - REST API 응답 데이터 검증 (
status
,header
,body
등) - API의 상태 코드 및 응답 값을 UI 요소와 비교 가능
- Playwright와 결합하여 API 백엔드와 프론트엔드가 동기화되었는지 검증 가능
2. Supertest 설치
Playwright 프로젝트에서 Supertest를 사용하려면 먼저 설치해야 합니다.
npm install --save-dev supertest @playwright/test
이제 Supertest
와 Playwright
를 함께 사용할 수 있습니다.
3. Supertest와 Playwright를 함께 사용한 예제
📌 시나리오
- API를 호출하여 특정 사용자 데이터를 가져온다.
- Playwright를 사용해 UI에 표시된 데이터가 API 응답과 동일한지 확인한다.
📌 API 예제 (https://jsonplaceholder.typicode.com/posts/1
)
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit..."
}
📌 Supertest + Playwright 코드 예제
import { test, expect } from '@playwright/test';
import request from 'supertest';
const API_URL = 'https://jsonplaceholder.typicode.com';
test('API 데이터와 UI 데이터 비교', async ({ page }) => {
// 1️⃣ API 요청을 수행하여 응답 데이터를 가져옴
const response = await request(API_URL).get('/posts/1');
expect(response.status).toBe(200); // 상태 코드 검증
const apiData = response.body;
expect(apiData).toHaveProperty('title'); // title 필드 확인
// 2️⃣ 웹 페이지 이동
await page.goto('https://example.com');
// 3️⃣ API 데이터와 UI 데이터 비교
const uiTitle = await page.locator('.post-title').textContent();
expect(uiTitle).toContain(apiData.title); // UI의 제목이 API 응답과 일치하는지 확인
});
✅ 설명
- Supertest를 사용해
GET
요청을 보냄request(API_URL).get('/posts/1')
를 호출하여 API 데이터를 가져옴.- API 응답 상태 코드가
200
인지 검증. title
필드가 존재하는지 확인.
- Playwright를 사용해 UI에서 데이터 확인
- 웹 페이지 (
https://example.com
)에 이동. .post-title
요소의 텍스트를 가져옴.- UI의
title
이 API 응답의title
과 일치하는지 검증.
- 웹 페이지 (
4. API를 통한 UI 사전 데이터 설정
실제 UI 테스트에서는 특정 데이터를 미리 생성해야 할 수도 있습니다.
Supertest를 활용하면 API를 호출하여 테스트 데이터를 미리 생성한 후 UI 테스트를 진행할 수 있습니다.
📌 API 호출을 통해 UI 테스트 전 데이터를 준비하는 예제
import { test, expect } from '@playwright/test';
import request from 'supertest';
const API_URL = 'https://jsonplaceholder.typicode.com';
test('API를 통해 데이터를 생성한 후 UI에서 확인', async ({ page }) => {
// 1️⃣ API 요청을 통해 새로운 데이터를 생성
const createResponse = await request(API_URL)
.post('/posts')
.send({
title: '테스트 제목',
body: '테스트 본문',
userId: 1,
});
expect(createResponse.status).toBe(201); // POST 요청 성공 검증
const createdPost = createResponse.body;
expect(createdPost).toHaveProperty('id');
// 2️⃣ UI에서 생성된 데이터 확인
await page.goto(`https://example.com/posts/${createdPost.id}`);
const uiTitle = await page.locator('.post-title').textContent();
expect(uiTitle).toContain('테스트 제목'); // UI의 제목이 API에서 생성한 데이터와 일치하는지 확인
});
✅ 설명
- Supertest를 사용해
POST /posts
요청을 보내서 새로운 데이터를 생성. - 생성된 데이터의
id
를 이용해 Playwright에서 해당 페이지로 이동. - UI에서 표시된 제목이 API를 통해 생성한 데이터와 일치하는지 확인.
5. Playwright API Request와 Supertest 비교
Playwright 자체적으로 API 테스트 기능을 제공하는 request
객체가 있습니다.
하지만 Supertest는 더 많은 HTTP 요청 옵션을 제공하며, 기존 API 테스트 코드와의 호환성이 높습니다.
기능 | Supertest (request() ) |
Playwright API Request (context.request() ) |
---|---|---|
HTTP 요청 지원 | ✅ GET , POST , PUT , DELETE , PATCH , HEAD 등 지원 |
✅ fetch 와 유사한 API |
요청 체이닝 가능 | ✅ .set() , .query() , .send() 등 메서드 체이닝 가능 |
❌ 직접 요청을 수행해야 함 |
상태 코드 확인 | ✅ .expect(200) 로 상태 코드 검증 |
✅ .ok() 및 status() 사용 가능 |
JSON 자동 파싱 | ✅ 응답을 자동으로 JSON 변환 |
✅ .json() 메서드 사용 |
쿠키/세션 관리 | ✅ .set('Cookie', 'session=12345') 가능 |
✅ Playwright의 storageState 활용 가능 |
Playwright 통합 | ✅ API 호출 후 UI 테스트 가능 | ✅ Playwright 네이티브 기능 사용 |
📌 언제 Supertest를 사용해야 할까?
- 기존 API 테스트 코드(Supertest 사용)가 많을 때 Playwright UI 테스트와 함께 사용
.set()
,.query()
같은 메서드를 활용한 복잡한 API 요청이 필요한 경우- Playwright API request보다 더 많은 기능이 필요한 경우
📌 Playwright API Request를 사용해야 할 때
- Playwright의 내장 API 요청 기능을 사용하여 API와 UI 테스트를 한 곳에서 관리할 때
- API 테스트가 많지 않고 단순한 요청만 필요할 때
- Supertest를 Playwright와 함께 사용하면 API 백엔드와 UI 데이터를 동기화하여 검증 가능
- API에서 가져온 데이터를 UI에서 제대로 렌더링했는지 검증 가능
- API를 이용한 사전 데이터 설정 (POST 요청 후 UI 확인) 가능
- Playwright의
request
기능도 있지만, Supertest는 더 다양한 요청 옵션과 API 테스트 기능 제공 - API와 UI가 함께 동작하는 E2E 테스트 시나리오에서 매우 유용함 🚀
📌 Supertest와 Playwright을 결합하면 강력한 API + UI 테스트를 구축할 수 있습니다!
사용자 지정 보고서 생성
Playwright에서 기본적으로 제공하는 HTML Report, Allure Report 외에도 사용자 지정 보고서(Custom Report) 를 생성할 수 있습니다.
테스트 데이터를 원하는 형식(JSON, CSV, Markdown 등)으로 저장하고, 이를 기반으로 맞춤형 보고서를 만들 수 있습니다.
1. 사용자 지정 보고서를 만드는 방법
Playwright는 Event Listener를 활용하여 테스트 실행 결과를 추적할 수 있습니다. 이를 기반으로 다음과 같은 방식으로 맞춤 보고서를 생성할 수 있습니다.
✅ 파일 형식에 따른 맞춤 보고서
- JSON 파일 → 분석 도구에서 활용 가능
- CSV 파일 → Excel에서 결과 정리
- Markdown 파일 → 간단한 문서화 보고서 생성
- HTML 파일 → 웹 기반 보고서 UI 제공
✅ 보고서 생성 방식
- Playwright의 Reporter API를 사용하여 자동화된 맞춤 보고서 생성
fs
모듈을 사용하여 JSON, Markdown, CSV 파일로 저장playwright.config.ts
에 사용자 정의 리포터 설정
2. JSON 기반 사용자 지정 보고서 생성
Playwright의 이벤트 리스너를 활용하여 테스트 실행 중 데이터를 JSON 파일에 저장할 수 있습니다.
📌 1) JSON 파일로 테스트 결과 저장
import { test, expect } from '@playwright/test';
import * as fs from 'fs';
// JSON 결과 저장을 위한 배열
const testResults: any[] = [];
test.afterEach(async ({ title }, testInfo) => {
testResults.push({
title: title, // 테스트 제목
status: testInfo.status, // 'passed' | 'failed' | 'skipped'
duration: testInfo.duration, // 실행 시간(ms)
});
fs.writeFileSync('test-results.json', JSON.stringify(testResults, null, 2), 'utf-8');
});
test('Example test 1', async ({ page }) => {
await page.goto('https://example.com');
expect(await page.title()).toBe('Example Domain');
});
test('Example test 2', async ({ page }) => {
await page.goto('https://example.com');
expect(await page.title()).toBe('Wrong Title'); // 실패하는 테스트
});
✅ 기능 설명
test.afterEach()
를 사용하여 각 테스트가 실행될 때마다 JSON 파일에 저장testInfo
객체에서 테스트 상태, 실행 시간 등을 가져와 JSON으로 저장fs.writeFileSync()
를 사용하여 결과를test-results.json
파일로 생성
3. CSV 형식 사용자 지정 보고서 생성
📌 CSV 파일을 생성하여 Excel 등에서 확인 가능
import { test } from '@playwright/test';
import * as fs from 'fs';
// CSV 저장을 위한 문자열 초기화
let csvReport = 'Test Name,Status,Duration (ms)\n';
test.afterEach(async ({ title }, testInfo) => {
csvReport += `${title},${testInfo.status},${testInfo.duration}\n`;
fs.writeFileSync('test-results.csv', csvReport, 'utf-8');
});
test('Test A', async ({ page }) => {
await page.goto('https://example.com');
});
test('Test B', async ({ page }) => {
await page.goto('https://example.com');
throw new Error('Intentional Failure'); // 실패하는 테스트
});
✅ 기능 설명
- CSV 파일을 생성하여
test-results.csv
파일에 저장 test.afterEach()
후fs.writeFileSync()
를 사용해 CSV 형식으로 결과 저장- 결과 파일을 Excel에서 쉽게 열어볼 수 있음
4. Markdown 기반 보고서 생성
📌 Markdown 형식의 보고서를 생성하여 GitHub에서 쉽게 확인 가능
import { test } from '@playwright/test';
import * as fs from 'fs';
// Markdown 초기화
let markdownReport = `# Playwright Test Report\n\n| Test Name | Status | Duration (ms) |\n|---|---|---|\n`;
test.afterEach(async ({ title }, testInfo) => {
markdownReport += `| ${title} | ${testInfo.status} | ${testInfo.duration} |\n`;
fs.writeFileSync('test-results.md', markdownReport, 'utf-8');
});
test('Markdown Test 1', async ({ page }) => {
await page.goto('https://example.com');
});
test('Markdown Test 2', async ({ page }) => {
await page.goto('https://example.com');
throw new Error('Test Failure'); // 실패하는 테스트
});
✅ 기능 설명
- Markdown 형식의 보고서를 생성 (
test-results.md
) - GitHub의 Markdown Viewer에서 쉽게 확인 가능
- 테이블 형식으로 정리하여 가독성 향상
5. HTML 기반 사용자 지정 보고서 생성
📌 HTML 파일로 저장하여 브라우저에서 테스트 결과를 시각적으로 확인 가능
import { test } from '@playwright/test';
import * as fs from 'fs';
let htmlReport = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Playwright Test Report</title>
<style>
table { width: 100%; border-collapse: collapse; }
th, td { border: 1px solid black; padding: 8px; text-align: left; }
th { background-color: #f4f4f4; }
</style>
</head>
<body>
<h1>Playwright Test Report</h1>
<table>
<tr>
<th>Test Name</th>
<th>Status</th>
<th>Duration (ms)</th>
</tr>
`;
test.afterEach(async ({ title }, testInfo) => {
htmlReport += `
<tr>
<td>${title}</td>
<td>${testInfo.status}</td>
<td>${testInfo.duration}</td>
</tr>
`;
fs.writeFileSync('test-results.html', htmlReport + '</table></body></html>', 'utf-8');
});
test('HTML Report Test 1', async ({ page }) => {
await page.goto('https://example.com');
});
test('HTML Report Test 2', async ({ page }) => {
await page.goto('https://example.com');
throw new Error('Test Failure');
});
✅ 기능 설명
test-results.html
파일이 생성되며, 브라우저에서 열어볼 수 있음table
태그를 사용하여 시각적인 보고서 제공fs.writeFileSync()
를 사용해 HTML 파일 업데이트
6. Playwright의 Reporter API를 활용한 커스텀 리포터
Playwright는 기본적으로 Reporter API를 제공하여 playwright.config.ts
에서 사용자 지정 리포터를 설정할 수 있습니다.
📌 Custom Reporter 설정 (playwright.config.ts)
import { defineConfig } from '@playwright/test';
export default defineConfig({
reporter: [
['json', { outputFile: 'custom-report.json' }],
['html', { outputFolder: 'playwright-report' }],
['./custom-reporter.ts'], // 사용자 지정 리포터 등록
],
});
📌 사용자 지정 리포터 (custom-reporter.ts
)
import { Reporter } from '@playwright/test/reporter';
import * as fs from 'fs';
class CustomReporter implements Reporter {
private results: any[] = [];
onTestEnd(test, result) {
this.results.push({
title: test.title,
status: result.status,
duration: result.duration,
});
}
onEnd() {
fs.writeFileSync('custom-test-results.json', JSON.stringify(this.results, null, 2), 'utf-8');
}
}
export default CustomReporter;
✅ Playwright에서 공식적으로 지원하는 Reporter API를 활용하여 맞춤형 보고서를 생성 가능
- JSON, CSV, Markdown, HTML 등 다양한 맞춤형 보고서 생성 가능
fs.writeFileSync()
를 활용하여 실시간 테스트 결과 저장- Playwright의 Reporter API를 활용하면 더욱 강력한 맞춤형 보고서 제작 가능 🚀
📌 커스텀 보고서는 자동화된 QA 프로세스에서 중요한 역할을 하므로 필요에 맞게 구성하는 것이 중요합니다! 🚀