Playwright 테스트 실행 및 디버깅
Playwright는 CLI 명령어와 디버깅 도구를 통해 효율적인 테스트 자동화를 제공합니다. 테스트 실행, 브라우저 설치, 코드 생성기와 같은 명령어로 작업을 간소화할 수 있으며, pause(), Playwright Inspector, Trace Viewer 등 디버깅 도구를 활용해 선택자 검증과 네트워크 상태를 분석할 수 있습니다. 또한, 병렬 실행, storage state 재사용, 스크린샷 및 비디오 기록 기능으로 테스트 속도와 안정성을 최적화할 수 있습니다.

테스트 실행 방법
CLI 명령어
Playwright는 CLI(Command Line Interface)를 제공하여 다양한 작업을 수행할 수 있습니다. 다음은 Playwright CLI의 주요 명령어와 설명입니다.
1. Playwright 설치
npm init playwright@latest
- Playwright 프로젝트를 초기화합니다. 필요한 종속성과 샘플 코드를 포함한 기본 프로젝트 구조를 설정합니다.
2. Playwright 테스트 실행
npx playwright test
- Playwright 테스트를 실행합니다. 디폴트로
tests
디렉토리에서.spec.ts
또는.spec.js
파일을 찾습니다.
옵션 예시
- 특정 테스트 파일 실행
npx playwright test tests/example.spec.ts
- 특정 테스트 이름 실행
npx playwright test -g "테스트 이름"
- 브라우저 지정
npx playwright test --project=chromium
- 실행 결과 요약
npx playwright test --reporter=html
3. Playwright 코드 생성기 실행
npx playwright codegen
- Playwright의 코드 생성기를 실행하여 테스트 코드 작성을 자동화합니다. 브라우저에서 수행된 작업이 기록되어 코드로 변환됩니다.
옵션 예시
- 특정 URL에서 시작
npx playwright codegen https://example.com
- 언어 지정 (예: Python)
npx playwright codegen --target python
4. 브라우저 설치 및 업데이트
npx playwright install
- Playwright에서 지원하는 브라우저(chromium, firefox, webkit)를 설치합니다.
특정 브라우저 설치
npx playwright install chromium
5. 브라우저를 GUI 모드로 실행
npx playwright show-trace trace.zip
- 테스트 실행 후 생성된 트레이스 파일을 GUI에서 분석합니다.
6. 환경 정보 확인
npx playwright info
- Playwright 및 브라우저 버전과 같은 환경 정보를 확인합니다.
7. 테스트 프로젝트 초기화
npx playwright test init
- Playwright 테스트 환경을 설정하기 위한 기본 템플릿과 설정 파일을 생성합니다.
8. Playwright 트레이스 보기
npx playwright show-trace
- 테스트 중 생성된 트레이스 파일을 시각적으로 분석할 수 있는 인터페이스를 실행합니다.
9. 스크린샷 및 PDF 생성
npx playwright screenshot --help
npx playwright pdf --help
- Playwright를 사용하여 특정 페이지의 스크린샷 또는 PDF를 생성합니다.
10. Playwright 제거
npx playwright uninstall
- Playwright와 관련된 브라우저 및 데이터를 삭제합니다.
필요한 작업에 따라 Playwright CLI 명령어를 적절히 활용하면, 효율적으로 자동화 테스트를 작성하고 실행할 수 있습니다!
병렬 실행과 테스트 속도 최적화
Playwright에서 테스트를 병렬로 실행하고 테스트 속도를 최적화하는 방법에 대해 알아보겠습니다. 이는 테스트 시간을 단축하고 효율성을 높이는 데 도움이 됩니다.
1. 병렬 실행 설정
Playwright는 기본적으로 테스트를 병렬로 실행하도록 설계되어 있습니다. 병렬 실행은 workers
설정을 통해 관리할 수 있습니다.
1.1 기본 병렬 실행
npx playwright test
- 기본적으로 Playwright는 CPU 코어 수에 따라 테스트를 병렬로 실행합니다.
1.2 병렬 워커 수 조정
playwright.config.ts
에서 병렬 워커 수를 직접 설정할 수 있습니다.
import { defineConfig } from '@playwright/test';
export default defineConfig({
workers: 4, // 워커 수를 4로 제한
});
또는 CLI에서 --workers
옵션을 사용하여 설정할 수도 있습니다.
npx playwright test --workers=4
2. 테스트 파일 및 시나리오 분할
2.1 테스트 파일 분리
- 테스트를 작은 파일 단위로 분할하면 Playwright가 병렬로 파일을 처리하여 성능이 향상됩니다.
2.2 독립적인 테스트 작성
- 테스트 간 데이터 공유를 피하고, 각 테스트가 독립적으로 실행되도록 작성합니다.
- Before Hooks 및 After Hooks를 활용하여 테스트 환경을 초기화합니다.
3. 브라우저 인스턴스 최적화
3.1 headless
모드 사용
브라우저를 headless
모드로 실행하면 UI 렌더링에 필요한 리소스를 줄여 속도가 빨라집니다.
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
headless: true, // 브라우저를 headless 모드로 실행
},
});
3.2 테스트 컨텍스트 재활용
브라우저를 테스트마다 새로 열지 않고, 컨텍스트를 재활용합니다.
import { chromium } from 'playwright';
let browser;
beforeAll(async () => {
browser = await chromium.launch();
});
afterAll(async () => {
await browser.close();
});
test('example', async () => {
const context = await browser.newContext();
const page = await context.newPage();
await page.goto('https://example.com');
});
4. 테스트 순서 및 우선순위 관리
4.1 중요한 테스트 우선 실행
중요도가 높은 테스트를 먼저 실행하도록 설정합니다.
npx playwright test --grep "critical"
- 테스트 파일 또는 이름에 태그를 추가하여 필터링할 수 있습니다.
5. 리소스 소비 줄이기
5.1 타임아웃 최소화
- 불필요하게 높은 타임아웃 값을 줄여 실행 시간을 단축합니다.
test.setTimeout(5000); // 5초 제한
5.2 HTTP 요청 Mocking
- 테스트가 외부 API 호출에 의존하지 않도록 Mocking을 사용하여 빠른 응답을 제공합니다.
test('mock example', async ({ page }) => {
await page.route('**/api/data', async route => {
await route.fulfill({
body: JSON.stringify({ success: true }),
});
});
await page.goto('https://example.com');
});
6. 테스트 결과 보고서 사용
Playwright의 보고서를 통해 병목 구간을 파악하고 최적화할 수 있습니다.
npx playwright test --reporter=html
- 테스트 실행 결과를 분석하여 실행 시간이 오래 걸리는 테스트를 개선합니다.
7. 캐싱 및 세션 재사용
7.1 storageState
활용
로그인 세션을 저장하고 재사용하여 매번 로그인하는 시간을 줄입니다.
import { test } from '@playwright/test';
test.use({ storageState: 'state.json' });
test('example', async ({ page }) => {
await page.goto('https://example.com/dashboard'); // 로그인 상태 유지
});
8. CI/CD에서 병렬 테스트 실행
CI/CD 환경에서 병렬로 테스트를 실행하여 실행 속도를 높일 수 있습니다.
8.1 GitHub Actions 예시
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
browser: [chromium, firefox, webkit]
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '16'
- run: npm install
- run: npx playwright test --project=${{ matrix.browser }}
이 방법들을 활용하면 Playwright 테스트를 효율적으로 병렬 실행하고 속도를 최적화할 수 있습니다.
Playwright에서 캐싱 및 세션 재사용은 테스트 속도와 효율성을 크게 향상시키는 중요한 최적화 기법입니다. 이를 통해 반복적인 작업(예: 로그인)을 최소화하고 테스트 실행 시간을 단축할 수 있습니다. 아래는 자세한 설명과 단계별 설정 방법입니다.
1. Storage State 저장 및 재사용
Playwright는 브라우저의 쿠키와 로컬 스토리지 데이터를 포함한 storage state를 파일로 저장하고 재사용할 수 있습니다. 이 방식은 주로 로그인 세션을 저장하고 테스트 시 재활용할 때 사용됩니다.
1.1 Storage State 저장
로그인 후 상태를 저장하려면 다음과 같은 스크립트를 작성합니다.
import { chromium } from 'playwright';
(async () => {
const browser = await chromium.launch();
const context = await browser.newContext();
const page = await context.newPage();
// 로그인 절차 수행
await page.goto('https://example.com/login');
await page.fill('#username', 'testuser'); // 사용자 이름 입력
await page.fill('#password', 'password'); // 비밀번호 입력
await page.click('button[type="submit"]'); // 로그인 버튼 클릭
// 로그인 성공 후 상태 저장
await context.storageState({ path: 'state.json' });
await browser.close();
})();
위 코드는 로그인 상태를 state.json
파일에 저장합니다. 이후 테스트에서 이 상태를 재활용할 수 있습니다.
1.2 저장된 상태를 재사용한 테스트
저장된 state.json
을 로드하여 테스트 실행 시 로그인 과정을 생략할 수 있습니다.
import { test } from '@playwright/test';
test.use({ storageState: 'state.json' });
test('example test using saved session', async ({ page }) => {
await page.goto('https://example.com/dashboard'); // 로그인 상태 유지
// 대시보드에서 동작 수행
await page.click('button#view-report');
});
- 이 방법은 테스트 실행 시 이미 로그인된 상태를 시뮬레이션하므로, 로그인 절차를 반복할 필요가 없습니다.
2. Storage State 활용 시 주의사항
2.1 파일 경로 관리
state.json
파일을 프로젝트의 루트 디렉토리에 두거나, 특정 폴더(예:tests/states/
)에 정리합니다.- CI/CD 환경에서도 이 파일을 쉽게 관리할 수 있도록 버전 관리나 생성 스크립트를 추가합니다.
2.2 사용자 상태 초기화
저장된 상태가 만료되거나 테스트에 문제가 발생할 경우, 새로운 state.json
파일을 생성해야 합니다.
2.3 민감 정보 보호
state.json
에 쿠키 및 로컬 스토리지 데이터가 포함되므로, 민감한 정보가 노출되지 않도록.gitignore
에 추가하거나 암호화를 고려합니다.
3. 멀티 유저 세션 관리
여러 사용자가 동시에 테스트에 참여하는 경우, 각 사용자의 storageState
파일을 개별적으로 관리해야 합니다.
3.1 예시: 멀티 유저 세션
test.describe('Multi-user session tests', () => {
test.use({ storageState: 'user1_state.json' });
test('User 1 dashboard test', async ({ page }) => {
await page.goto('https://example.com/dashboard');
// User 1 동작 수행
});
test.use({ storageState: 'user2_state.json' });
test('User 2 dashboard test', async ({ page }) => {
await page.goto('https://example.com/dashboard');
// User 2 동작 수행
});
});
- 각 테스트는 별도의 사용자 세션에서 실행됩니다.
- 사용자별
state.json
파일을 사전에 생성해 두는 것이 중요합니다.
4. 세션 재사용과 테스트 병렬화
Playwright는 기본적으로 병렬 실행을 지원하므로, 세션 재사용과 병렬화 기능을 결합하면 테스트 속도를 더욱 최적화할 수 있습니다.
4.1 storageState
와 병렬 실행
병렬 실행 시 각 워커가 자신의 storageState
를 사용할 수 있도록 설정합니다.
import { defineConfig } from '@playwright/test';
export default defineConfig({
projects: [
{
name: 'User 1',
use: { storageState: 'user1_state.json' },
},
{
name: 'User 2',
use: { storageState: 'user2_state.json' },
},
],
});
- 이 설정은 서로 다른 사용자의 상태를 기반으로 병렬 테스트를 실행합니다.
5. 세션 초기화 자동화
테스트가 시작될 때마다 로그인 상태를 자동으로 생성하려면 globalSetup
을 활용할 수 있습니다.
5.1 globalSetup
파일 작성
// global-setup.ts
import { chromium, FullConfig } from '@playwright/test';
async function globalSetup(config: FullConfig) {
const browser = await chromium.launch();
const context = await browser.newContext();
const page = await context.newPage();
// 로그인 수행
await page.goto('https://example.com/login');
await page.fill('#username', 'testuser');
await page.fill('#password', 'password');
await page.click('button[type="submit"]');
// 상태 저장
await context.storageState({ path: 'state.json' });
await browser.close();
}
export default globalSetup;
5.2 playwright.config.ts
에 설정 추가
import { defineConfig } from '@playwright/test';
export default defineConfig({
globalSetup: require.resolve('./global-setup'), // global-setup.ts 경로
use: {
storageState: 'state.json',
},
});
- 이 설정은 테스트 실행 전에 자동으로 로그인 상태를 생성하고 저장합니다.
6. 캐싱 및 세션 재사용의 장점
- 테스트 속도 향상: 반복적인 로그인 과정을 생략하여 테스트 실행 시간을 단축합니다.
- 리소스 절약: 브라우저 및 서버 리소스를 줄여 테스트 환경의 부하를 감소시킵니다.
- 테스트 안정성 향상: 로그인을 포함한 초기 설정이 동일하게 유지되므로 테스트 간 일관성이 높아집니다.
- 다양한 시나리오 지원: 사용자별 상태 관리로 복잡한 멀티 유저 테스트 시나리오를 쉽게 처리할 수 있습니다.
위 방법들을 통해 Playwright 테스트에서 세션 재사용과 캐싱을 효과적으로 활용할 수 있습니다.
테스트 중에 사용자별 state.json
파일을 동적으로 생성 및 관리하며, 테스트 종료 후 해당 파일을 자동 삭제하는 것을 포함합니다. 아래는 이를 구현하기 위한 단계별 설정 방법입니다.
1. 전체 구조
- 로그인 상태 관리: 테스트 시작 시
state.json
이 없으면 로그인 과정을 수행하고state.json
을 생성합니다. - 파일 삭제: 테스트 종료 시 사용자별
state.json
을 삭제합니다. - 상태 공유: 이미 생성된
state.json
이 있으면 로그인 절차를 스킵하고 재사용합니다.
이를 위해 Playwright의 globalSetup
, globalTeardown
, 및 테스트 내부 로직을 조합하여 구현합니다.
2. 디렉토리 및 파일 설정
사용자별 state.json
파일을 저장하고 삭제하기 위해 별도의 디렉토리를 설정합니다.
2.1 디렉토리 구조
project/
├── states/
│ ├── user1_state.json
│ ├── user2_state.json
├── global-setup.ts
├── global-teardown.ts
├── playwright.config.ts
├── tests/
states/
: 사용자별 상태 파일을 저장하는 디렉토리.
3. globalSetup
구현
3.1 global-setup.ts
globalSetup
에서는 테스트 시작 전에 사용자별 state.json
이 존재하는지 확인하고, 없으면 로그인 후 상태를 저장합니다.
import { chromium, FullConfig } from '@playwright/test';
import fs from 'fs';
import path from 'path';
async function globalSetup(config: FullConfig) {
const users = ['user1', 'user2']; // 사용자 ID 목록
const statesDir = path.resolve(__dirname, 'states');
// 상태 디렉토리가 없으면 생성
if (!fs.existsSync(statesDir)) {
fs.mkdirSync(statesDir);
}
for (const user of users) {
const statePath = path.join(statesDir, `${user}_state.json`);
if (!fs.existsSync(statePath)) {
console.log(`[INFO] ${user} 로그인 후 state.json 생성`);
const browser = await chromium.launch();
const context = await browser.newContext();
const page = await context.newPage();
// 로그인 수행 (사용자 ID와 비밀번호를 사용)
await page.goto('https://example.com/login');
await page.fill('#username', user); // 사용자 ID 입력
await page.fill('#password', 'password'); // 비밀번호 입력
await page.click('button[type="submit"]');
// state.json 저장
await context.storageState({ path: statePath });
await browser.close();
} else {
console.log(`[INFO] ${user}의 state.json이 이미 존재합니다. 로그인 스킵`);
}
}
}
export default globalSetup;
4. globalTeardown
구현
4.1 global-teardown.ts
테스트가 종료되면 states/
디렉토리의 모든 state.json
파일을 삭제합니다.
import fs from 'fs';
import path from 'path';
async function globalTeardown() {
const statesDir = path.resolve(__dirname, 'states');
if (fs.existsSync(statesDir)) {
const files = fs.readdirSync(statesDir);
for (const file of files) {
fs.unlinkSync(path.join(statesDir, file));
console.log(`[INFO] ${file} 삭제 완료`);
}
}
}
export default globalTeardown;
5. Playwright 설정 파일
Playwright의 playwright.config.ts
파일에서 globalSetup
과 globalTeardown
을 추가로 설정합니다.
5.1 playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
globalSetup: require.resolve('./global-setup'),
globalTeardown: require.resolve('./global-teardown'),
use: {
headless: true, // Headless 모드로 실행
baseURL: 'https://example.com', // 기본 URL 설정
},
projects: [
{
name: 'User 1',
use: { storageState: 'states/user1_state.json' },
},
{
name: 'User 2',
use: { storageState: 'states/user2_state.json' },
},
],
});
- 사용자별
storageState
파일이 프로젝트에 매핑됩니다. - 테스트 실행 시 각 사용자가 별도의 세션을 사용합니다.
6. 테스트 구현
테스트는 상태 파일을 기반으로 사용자별로 실행됩니다.
6.1 tests/example.spec.ts
import { test } from '@playwright/test';
test.describe('User-specific tests', () => {
test('User 1 dashboard test', async ({ page }) => {
await page.goto('/dashboard');
await page.click('button#view-report');
console.log('[INFO] User 1의 대시보드 테스트 완료');
});
test('User 2 dashboard test', async ({ page }) => {
await page.goto('/dashboard');
await page.click('button#submit-form');
console.log('[INFO] User 2의 대시보드 테스트 완료');
});
});
7. 주요 동작 흐름
- 테스트 시작 전 (
globalSetup
):state.json
파일이 존재하지 않으면 자동으로 로그인하고 파일을 생성.state.json
이 이미 존재하면 로그인 절차를 생략.
- 테스트 실행 중
- 각 테스트는 사용자의
state.json
을 로드하여 로그인 상태를 유지.
- 각 테스트는 사용자의
- 테스트 종료 후 (
globalTeardown
):- 모든 사용자
state.json
파일을 자동으로 삭제하여 정리.
- 모든 사용자
8. 추가 최적화
- 테스트 병렬화: 테스트 병렬화와 함께 동작하도록 설정하면 테스트 속도가 더욱 빨라집니다.
- 로그인 실패 처리: 로그인에 실패한 경우 예외를 던져 사용자 상태를 재생성할 수 있도록 설정합니다.
- 환경 변수 활용: 사용자 ID와 비밀번호를 코드에 직접 작성하지 않고, 환경 변수에서 가져오도록 설정합니다.
위의 설정을 통해 Playwright 테스트에서 동적인 state.json
생성, 관리, 삭제가 자동화됩니다.
Playwright에서 글로벌 설정(globalSetup
)으로 로그인 상태를 관리할 때, 특정 테스트는 로그인 상태 없이 시작해야 하거나 테스트 서버 환경마다 로그인 상태가 달라야 할 수 있습니다. 이를 해결하기 위해 테스트 환경과 테스트별 동작을 분리하고 유연하게 설정하는 방법을 제안합니다.
1. 요구사항 분석
- 특정 테스트는 로그인 없이 시작해야 함 (예: 로그인 테스트).
- 테스트 서버 환경에 따라 별도의 로그인 상태를 유지해야 함.
- 상태 파일(
state.json
)은 환경별로 관리되며, 필요에 따라 자동 생성 및 삭제. - 로그인 상태를 공유하지 않는 테스트도 쉽게 구현 가능해야 함.
2. 솔루션: 상태 관리와 유연한 설정
2.1 글로벌 로그인과 테스트별 로그인 분리
- 글로벌 상태: 대부분의 테스트에서 사용할 로그인 상태를 자동 생성.
- 테스트별 상태: 로그인 상태를 공유하지 않거나 새로 생성이 필요한 경우, 테스트 내에서 별도로 처리.
2.2 환경별 로그인 상태 파일 관리
테스트 서버 환경에 따라 상태 파일을 분리 저장합니다. 예를 들어, 개발, 스테이징, 프로덕션 환경마다 다른 state.json
을 유지합니다.
- 환경 변수(
process.env
)를 통해 테스트 서버 환경을 전달받고 상태 파일 경로를 동적으로 설정합니다.
3. 구현: 상태 관리와 테스트 설정
3.1 글로벌 로그인 구현 (환경별 상태 관리 포함)
global-setup.ts
에서는 테스트 서버 환경과 사용자별 상태 파일을 동적으로 생성합니다.
import { chromium, FullConfig } from '@playwright/test';
import fs from 'fs';
import path from 'path';
async function globalSetup(config: FullConfig) {
const env = process.env.TEST_ENV || 'dev'; // 기본값은 'dev'
const users = ['user1', 'user2']; // 사용자 목록
const statesDir = path.resolve(__dirname, `states/${env}`); // 환경별 디렉토리
// 상태 디렉토리가 없으면 생성
if (!fs.existsSync(statesDir)) {
fs.mkdirSync(statesDir, { recursive: true });
}
for (const user of users) {
const statePath = path.join(statesDir, `${user}_state.json`);
if (!fs.existsSync(statePath)) {
console.log(`[INFO] ${env} 환경에서 ${user} 로그인 후 state.json 생성`);
const browser = await chromium.launch();
const context = await browser.newContext();
const page = await context.newPage();
// 로그인 수행
await page.goto(`https://${env}.example.com/login`);
await page.fill('#username', user);
await page.fill('#password', 'password');
await page.click('button[type="submit"]');
// 상태 저장
await context.storageState({ path: statePath });
await browser.close();
} else {
console.log(`[INFO] ${env} 환경에서 ${user}의 state.json이 이미 존재합니다. 로그인 스킵`);
}
}
}
export default globalSetup;
3.2 글로벌 상태 제거 (환경별 파일 삭제)
global-teardown.ts
는 테스트 종료 후 환경별 상태 파일을 삭제합니다.
import fs from 'fs';
import path from 'path';
async function globalTeardown() {
const env = process.env.TEST_ENV || 'dev'; // 기본값은 'dev'
const statesDir = path.resolve(__dirname, `states/${env}`);
if (fs.existsSync(statesDir)) {
const files = fs.readdirSync(statesDir);
for (const file of files) {
fs.unlinkSync(path.join(statesDir, file));
console.log(`[INFO] ${env} 환경에서 ${file} 삭제 완료`);
}
}
}
export default globalTeardown;
3.3 playwright.config.ts
설정
테스트 환경 및 사용자별 상태를 반영하도록 Playwright 설정을 업데이트합니다.
import { defineConfig } from '@playwright/test';
import path from 'path';
const env = process.env.TEST_ENV || 'dev'; // 기본값은 'dev'
export default defineConfig({
globalSetup: require.resolve('./global-setup'),
globalTeardown: require.resolve('./global-teardown'),
use: {
headless: true,
baseURL: `https://${env}.example.com`, // 환경에 따라 URL 변경
},
projects: [
{
name: 'User 1',
use: { storageState: path.resolve(__dirname, `states/${env}/user1_state.json`) },
},
{
name: 'User 2',
use: { storageState: path.resolve(__dirname, `states/${env}/user2_state.json`) },
},
],
});
3.4 로그인 상태를 사용하지 않는 테스트
특정 테스트에서 로그인 상태를 사용하지 않으려면, storageState
를 제거하거나 새로 생성합니다.
import { test } from '@playwright/test';
test.describe('No Login Tests', () => {
test('should load login page', async ({ page }) => {
await page.goto('/login');
await page.fill('#username', 'testuser');
await page.fill('#password', 'password');
await page.click('button[type="submit"]');
await page.waitForURL('/dashboard');
console.log('[INFO] 로그인 테스트 완료');
});
});
3.5 로그인 상태가 없는 경우 자동 생성
테스트 내부에서 상태 파일이 없으면 자동 생성하도록 처리할 수도 있습니다.
import fs from 'fs';
import path from 'path';
import { test } from '@playwright/test';
const env = process.env.TEST_ENV || 'dev';
const statePath = path.resolve(__dirname, `states/${env}/user1_state.json`);
test.describe('Dynamic Login Tests', () => {
test.beforeEach(async ({ page, context }) => {
if (!fs.existsSync(statePath)) {
console.log('[INFO] state.json이 없으므로 로그인 수행');
await page.goto('/login');
await page.fill('#username', 'user1');
await page.fill('#password', 'password');
await page.click('button[type="submit"]');
await context.storageState({ path: statePath });
} else {
console.log('[INFO] state.json이 존재하므로 로그인 스킵');
await context.addCookies([{ name: 'session', value: 'dummy', domain: `.${env}.example.com` }]);
}
});
test('should use existing session', async ({ page }) => {
await page.goto('/dashboard');
console.log('[INFO] 대시보드 테스트 완료');
});
});
4. 주요 동작 요약
- 환경별 상태 관리:
TEST_ENV
값을 기반으로 상태 파일과 URL을 관리. - 글로벌 상태와 독립 상태 분리: 필요 시 로그인 상태를 공유하지 않는 테스트도 작성 가능.
- 자동 상태 생성: 상태 파일이 없으면 자동으로 로그인 수행.
- 상태 파일 정리: 테스트 종료 후 각 환경별로 상태 파일 자동 삭제.
이 설정을 통해 환경별 상태 관리와 테스트별 유연한 로그인 처리가 가능합니다.
테스트 디버깅
Debugging Tools 활용
Playwright는 디버깅을 위한 다양한 도구를 제공합니다. 디버깅 도구를 활용하면 테스트 작성, 실행, 문제 해결 과정을 더 빠르고 효과적으로 수행할 수 있습니다. 여기서는 Playwright에서 제공하는 주요 디버깅 도구와 활용 방법을 자세히 설명하겠습니다.
1. --debug
옵션
Playwright에서 가장 간단히 디버깅 모드를 활성화하는 방법입니다.
사용법
npx playwright test --debug
동작
- 브라우저가 headful 모드(GUI가 보이는 상태)로 실행됩니다.
- 각 단계에서 디버깅을 위해 중단점과 함께 실행 상태를 관찰할 수 있습니다.
- Playwright Inspector가 활성화되어, 상호작용하며 문제를 분석할 수 있습니다.
2. Playwright Inspector
Playwright Inspector는 테스트 실행 중 DOM 요소를 확인하고 상호작용하며 문제를 디버깅할 수 있는 도구입니다.
활성화 방법
--debug
명령어로 실행
npx playwright test --debug
코드에서 test.use
를 통해 설정
import { test } from '@playwright/test';
test.use({ launchOptions: { headless: false } });
test('example test', async ({ page }) => {
await page.goto('https://example.com');
});
기능
- Element Highlighting: 마우스를 올려 특정 DOM 요소를 확인.
- Step Through Execution: 각 테스트 단계를 한 단계씩 실행.
- Live Selector Testing: 선택자 입력 후 요소가 선택되는지 실시간으로 확인.
3. pause()
함수
Playwright 코드에서 특정 지점에서 실행을 중단하고, 브라우저 상태를 분석할 수 있습니다.
사용법
import { test } from '@playwright/test';
test('pause example', async ({ page }) => {
await page.goto('https://example.com');
await page.pause(); // 이 시점에서 Playwright Inspector 활성화
});
활용
- 특정 단계에서 브라우저의 DOM 상태를 직접 확인.
- 실행 중단 후 선택자 검증이나 상호작용 테스트 수행.
4. debug: true
설정
Playwright 설정 파일에서 디버그 모드를 항상 활성화하도록 구성할 수 있습니다.
사용법
playwright.config.ts
에 디버그 설정 추가
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
headless: false, // GUI를 활성화
launchOptions: {
slowMo: 50, // 각 동작을 50ms 간격으로 느리게 실행
},
},
});
효과
- 테스트 실행 시 브라우저 동작을 눈으로 확인 가능.
- 각 단계별 동작을 천천히 확인하며 문제를 진단.
5. slowMo
모드
동작을 느리게 실행하여, 빠르게 지나가는 테스트를 눈으로 관찰할 수 있게 합니다.
사용법
CLI에서 실행
npx playwright test --slow-mo=100
- 각 동작을 100ms 간격으로 실행.
설정 파일에서 추가
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
launchOptions: {
slowMo: 100, // 동작을 느리게 실행
},
},
});
6. Video와 Screenshot 캡처
테스트 실행 중의 과정을 비디오나 스크린샷으로 기록하여, 실패 원인을 분석할 때 활용할 수 있습니다.
비디오 캡처
playwright.config.ts
에서 설정
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
video: 'on', // 비디오 기록 활성화
},
});
스크린샷 캡처
export default defineConfig({
use: {
screenshot: 'on', // 테스트 실패 시 스크린샷 생성
},
});
특정 테스트에서 사용
test('screenshot example', async ({ page }) => {
await page.goto('https://example.com');
await page.screenshot({ path: 'screenshot.png' }); // 스크린샷 저장
});
7. Trace Viewer
Trace Viewer는 Playwright 테스트 실행 중의 모든 동작(네트워크 요청, DOM 변경 등)을 기록하고, 이를 시각적으로 분석할 수 있는 도구입니다.
Trace 파일 생성
playwright.config.ts
에서 Trace 설정
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
trace: 'on-first-retry', // 테스트 실패 시 Trace 파일 생성
},
});
Trace 파일 분석
Trace 파일 확인
npx playwright show-trace trace.zip
Trace Viewer를 통해 다음 정보 확인
- DOM 스냅샷.
- 네트워크 요청/응답.
- 이벤트 타임라인.
8. Network Request 및 Response Mocking
테스트 중 네트워크 요청/응답을 디버깅하거나 Mock 데이터를 사용하여 특정 시나리오를 테스트할 수 있습니다.
사용법
test('mocking example', async ({ page }) => {
await page.route('**/api/data', route => {
route.fulfill({
status: 200,
body: JSON.stringify({ message: 'Mocked Response' }),
});
});
await page.goto('https://example.com');
// Mock된 응답을 확인
});
활용
- 서버가 응답하지 않는 경우 Mock 데이터를 사용하여 디버깅.
- API의 다양한 상태(예: 500 에러) 시나리오를 테스트.
9. VS Code Debugger와 연동
Playwright는 VS Code의 디버거와 연동할 수 있어, 테스트를 코드 단위로 디버깅할 수 있습니다.
설정 방법
launch.json
파일 생성
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Debug Playwright Tests",
"program": "${workspaceFolder}/node_modules/playwright/lib/cli.js",
"args": ["test", "--project=chromium"],
"cwd": "${workspaceFolder}",
"env": {
"DEBUG": "pw:api" // Playwright 디버그 로깅 활성화
}
}
]
}
VS Code에서 디버깅 시작
- 디버그 탭에서 위 설정을 선택하고 테스트를 디버깅.
10. Playwright Logger
Playwright에서 내부 동작을 기록하여 디버깅에 활용할 수 있습니다.
로깅 활성화
CLI에서 실행
DEBUG=pw:api npx playwright test
로깅 내용
- API 호출 정보.
- 선택자 매칭 결과.
- 브라우저 이벤트.
이와 같은 다양한 디버깅 도구를 활용하면 테스트 작성과 문제 해결 과정에서 효율성과 정확성을 크게 높일 수 있습니다.
스크린샷과 비디오 기록
Playwright는 스크린샷과 비디오 기록 기능을 제공하여 테스트 실행 중 발생하는 문제를 시각적으로 확인할 수 있습니다. 이 기능을 사용하면 실패한 테스트나 특정 시점의 화면 상태를 기록하여 문제 해결에 도움을 줄 수 있습니다. 아래에서 스크린샷과 비디오 기록 설정 및 사용 방법을 상세히 설명하겠습니다.
1. 스크린샷 설정
1.1 Playwright 설정 파일에서 스크린샷 활성화
playwright.config.ts
에서 스크린샷 옵션을 설정합니다.
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
screenshot: 'only-on-failure', // 실패한 테스트에서만 스크린샷 기록
},
});
스크린샷 옵션
'off'
: 스크린샷 비활성화.'on'
: 모든 테스트에서 스크린샷 기록.'only-on-failure'
: 실패한 테스트에서만 스크린샷 기록.
1.2 특정 테스트에서 스크린샷 저장
테스트 코드에서 스크린샷을 직접 저장할 수도 있습니다.
import { test } from '@playwright/test';
test('Take a screenshot', async ({ page }) => {
await page.goto('https://example.com');
await page.screenshot({ path: 'screenshot.png' }); // 스크린샷 저장
});
옵션
path
: 스크린샷 저장 경로.fullPage
:true
로 설정하면 페이지 전체를 스크린샷에 포함.clip
: 특정 영역만 캡처할 때 사용 (예:{ x: 0, y: 0, width: 800, height: 600 }
).
1.3 테스트 중 특정 요소 캡처
페이지 전체가 아닌 특정 요소를 캡처하려면 다음과 같이 설정합니다.
test('Capture specific element', async ({ page }) => {
await page.goto('https://example.com');
const element = await page.locator('h1'); // 캡처할 요소 선택
await element.screenshot({ path: 'element.png' }); // 해당 요소의 스크린샷 저장
});
2. 비디오 기록 설정
Playwright는 테스트 실행 과정을 비디오로 기록할 수 있습니다.
2.1 Playwright 설정 파일에서 비디오 활성화
playwright.config.ts
에서 비디오 옵션을 설정합니다.
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
video: 'retain-on-failure', // 실패한 테스트에서만 비디오 기록
},
});
비디오 옵션
'off'
: 비디오 기록 비활성화.'on'
: 모든 테스트에서 비디오 기록.'retain-on-failure'
: 실패한 테스트에서만 비디오 기록.'on-first-retry'
: 첫 번째 재시도에서만 비디오 기록.
2.2 테스트 실행 중 비디오 저장
비디오를 특정 테스트 실행에만 저장하려면 다음과 같이 설정합니다.
test('Record video of a test', async ({ page, context }) => {
const videoContext = await context.newContext({ recordVideo: { dir: 'videos/' } });
const videoPage = await videoContext.newPage();
await videoPage.goto('https://example.com');
await videoPage.click('text=Get Started');
await videoContext.close(); // 비디오 저장
});
옵션
dir
: 비디오 파일 저장 디렉토리.size
: 비디오 캡처 크기 지정 (예:{ width: 1280, height: 720 }
).
2.3 저장된 비디오 파일 확인
비디오 파일은 설정한 디렉토리에 .webm
형식으로 저장됩니다. 이를 지원하는 미디어 플레이어(예: VLC, Chrome 등)로 열어 실행 과정을 확인할 수 있습니다.
3. 스크린샷과 비디오 기록의 활용 사례
- 테스트 실패 시 디버깅
- 스크린샷과 비디오를 통해 실패한 시점의 화면 상태를 정확히 파악.
- 비디오를 통해 실패 직전의 모든 상호작용 흐름 확인.
- UI 변화 검증
- 스크린샷 비교를 통해 UI 변경 사항 추적.
- 비디오 기록을 통해 애니메이션이나 동적 콘텐츠의 정상 동작 확인.
- 리뷰 및 공유
- 테스트 실행 결과를 팀원들과 공유하여 협업 강화.
4. 스크린샷 비교를 통한 UI 테스트
4.1 기본 설정
Playwright는 스크린샷 비교를 지원하여 UI가 변경되지 않았는지 확인할 수 있습니다.
test('Visual comparison', async ({ page }) => {
await page.goto('https://example.com');
expect(await page.screenshot()).toMatchSnapshot('expected.png');
});
4.2 설정 파일에서 Snapshot 경로 정의
playwright.config.ts
에서 Snapshot 경로를 설정합니다.
export default defineConfig({
testDir: './tests',
snapshotDir: './snapshots',
});
4.3 UI 변경 감지
- Snapshot과 테스트 중 생성된 스크린샷을 비교하여 UI 변경 사항이 있는지 확인합니다.
- 변경 사항이 있을 경우, 업데이트된 스냅샷을 반영하려면
--update-snapshots
옵션을 사용합니다.
npx playwright test --update-snapshots
5. Playwright Test Report에서 스크린샷과 비디오 확인
테스트 실행 후, HTML 보고서를 통해 스크린샷과 비디오를 확인할 수 있습니다.
HTML 리포트 생성
npx playwright test --reporter=html
리포트 확인
playwright-report/
디렉토리에 생성된 HTML 파일을 열어 스크린샷과 비디오를 확인할 수 있습니다.- 실패한 테스트에 대한 비디오 및 스크린샷이 포함됩니다.
Playwright의 스크린샷과 비디오 기록은 테스트 실행 중 발생한 문제를 시각적으로 파악할 수 있는 강력한 도구입니다. 이를 활용하여 UI 테스트와 디버깅 프로세스를 더욱 효율적으로 수행할 수 있습니다.
디버깅용 pause 기능
Playwright의 pause()
기능은 디버깅에 매우 유용한 도구로, 테스트 실행을 일시 중지하고 브라우저 상태를 직접 확인하거나 테스트 흐름을 상호작용하면서 분석할 수 있게 합니다. 이 기능을 활용하면 선택자 검증, DOM 상태 확인, 네트워크 요청 분석 등이 가능합니다. 아래에서 자세한 사용 방법과 주요 활용 사례를 설명하겠습니다.
1. pause()
의 기본 사용법
pause()
는 테스트 실행 중 특정 지점에서 브라우저를 멈추고 Playwright Inspector를 활성화합니다.
사용 예제
import { test } from '@playwright/test';
test('Debugging with pause', async ({ page }) => {
await page.goto('https://example.com'); // 페이지 로드
await page.pause(); // 실행 중단
await page.click('text=Get Started'); // 이후 단계는 수동으로 확인 후 진행
});
동작
- Playwright Inspector가 열리며, 브라우저 상태를 시각적으로 확인할 수 있습니다.
- 이후 단계를 수동으로 진행하거나, DOM 요소를 실시간으로 검사할 수 있습니다.
2. Playwright Inspector의 주요 기능
pause()
를 사용하면 Playwright Inspector가 자동으로 활성화됩니다. Inspector에서 제공하는 주요 기능은 다음과 같습니다.
2.1 요소 선택 및 확인
- 브라우저 화면에서 DOM 요소에 마우스를 올리면 선택자 정보를 실시간으로 확인할 수 있습니다.
- 클릭, 입력 등 요소와 상호작용을 직접 시도해볼 수 있습니다.
2.2 스크립트 단계별 실행
- Inspector UI에서 다음과 같은 버튼을 사용하여 테스트를 단계별로 실행하거나 건너뛸 수 있습니다.
- Step: 다음 명령을 한 단계 실행.
- Resume: 중단된 실행을 계속 진행.
- Break: 특정 조건에서 중단.
2.3 실시간 선택자 테스트
- Inspector의 "Target Selector" 창에 CSS, XPath 또는 Playwright의 다른 선택자를 입력하여 요소 선택 가능 여부를 테스트할 수 있습니다.
2.4 네트워크 요청 및 응답 확인
- 네트워크 탭에서 HTTP 요청 및 응답 데이터를 확인할 수 있습니다.
3. CLI에서 디버깅 모드 활성화
pause()
없이도 CLI에서 디버깅 모드를 활성화할 수 있습니다. 이는 테스트 실행 시 바로 Playwright Inspector를 열어줍니다.
명령어
npx playwright test --debug
효과
- 모든 테스트 실행이 브라우저 GUI에서 시작됩니다.
- Inspector를 통해 상호작용하며 문제를 해결할 수 있습니다.
4. 조건부 디버깅
특정 조건에서만 pause()
를 실행하도록 설정할 수 있습니다.
조건부 예제
test('Conditional pause', async ({ page }) => {
await page.goto('https://example.com');
// 특정 조건에서 pause() 실행
if (await page.title() === 'Example Domain') {
await page.pause(); // 조건이 만족될 때만 디버깅 활성화
}
await page.click('text=Get Started');
});
5. Headless 모드에서 pause()
사용
pause()
는 브라우저가 headful 모드(GUI가 활성화된 상태)에서만 동작합니다. 따라서 headless
옵션을 꺼야 합니다.
방법
테스트 코드에서 headless
를 false로 설정
import { test } from '@playwright/test';
test.use({ launchOptions: { headless: false } }); // GUI 활성화
test('Pause with headful browser', async ({ page }) => {
await page.goto('https://example.com');
await page.pause();
});
CLI에서 설정
npx playwright test --headed
6. pause()
와 다른 디버깅 도구의 결합
pause()
는 다른 디버깅 기능과 함께 사용할 때 더욱 강력해집니다.
6.1 slowMo
와 결합
- 테스트 동작을 느리게 실행하여, 디버깅을 더 쉽게 수행할 수 있습니다.
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
launchOptions: {
slowMo: 100, // 각 동작을 100ms 간격으로 느리게 실행
},
},
});
6.2 Trace Viewer와 결합
pause()
로 브라우저 상태를 점검한 후,trace
를 활성화하여 실행 기록을 분석.
export default defineConfig({
use: {
trace: 'on-first-retry',
},
});
7. pause()
의 활용 사례
7.1 선택자 디버깅
- 특정 선택자가 올바르게 작동하지 않을 때
pause()
로 브라우저를 멈추고 선택자 검증. - Inspector에서 선택자가 올바른 요소를 선택하는지 직접 테스트.
7.2 애니메이션 또는 동적 콘텐츠 확인
- 페이지 내 애니메이션이 예상대로 작동하지 않을 경우,
pause()
로 중단 후 상호작용.
7.3 테스트 실패 원인 분석
- 특정 단계에서 중단하여 상태를 확인하고, 실패의 원인을 빠르게 식별.
8. pause()
를 활용한 효율적인 디버깅 전략
- 문제 단계 식별: 테스트에서 실패하는 특정 단계를 찾아 그 지점에
pause()
삽입. - 조건부 중단 설정: 특정 조건에서만 디버깅을 활성화해, 필요 없는 중단을 방지.
- Inspector의 실시간 디버깅: 선택자와 네트워크 상태를 실시간으로 확인.
- Trace Viewer 사용: 실행 기록을 분석하여 테스트 전체 흐름 이해.
9. 주의사항
pause()
는 테스트 자동화를 멈추기 때문에 CI/CD 환경에서는 사용하지 않는 것이 좋습니다.pause()
사용 후 테스트 코드에서 제거하지 않으면 불필요한 중단이 발생할 수 있으니 디버깅 후 반드시 코드 정리.
Playwright의 pause()
기능은 빠르고 정확한 디버깅을 지원하는 강력한 도구입니다. 이를 적절히 활용하면 테스트 작성과 문제 해결 시간이 크게 단축됩니다.