용어집 · UI 자동화
웹 퍼스트 어설션
영어: Web-first assertion
다른 이름: web-first assertions, 웹 우선 어설션, 자동 재시도 어설션, auto-retrying assertion
정의
값을 한 번만 확인하지 않고, 로케이터를 받아 기대 조건이 충족되거나 타임아웃이 끝날 때까지 재시도하는 Playwright 어설션입니다.
웹 퍼스트 어설션은 페이지가 아직 바뀌는 중일 수 있다는 점을 이해하는 어설션(assertion)입니다. 로케이터와 기대 조건을 넘기면 Playwright는 조건이 통과하거나 expect 타임아웃(기본 5초)이 끝날 때까지 요소를 다시 읽고 조건을 다시 확인합니다. 이 이름은 Playwright 공식 문서에서 나왔으며, 문서는 값을 직접 읽어서 비교하는 방식보다 이 어설션을 권장합니다.
예시
import { test, expect } from '@playwright/test';
test('shows the saved message', async ({ page }) => {
await page.goto('/settings');
await page.getByRole('button', { name: 'Save' }).click();
// Web-first: retries until the text matches
await expect(page.getByRole('status')).toHaveText('Settings saved');
await expect(page.getByRole('progressbar')).toBeHidden();
await expect(page.getByRole('listitem')).toHaveCount(3);
await expect(page).toHaveURL(/\/settings$/);
});
일반 어설션과의 차이
// Not web-first: reads the text once, then compares
expect(await page.getByRole('status').textContent()).toBe('Settings saved');
// Not web-first: isVisible() returns immediately
expect(await page.getByRole('dialog').isVisible()).toBe(true);
두 줄 모두 한순간의 페이지만 확인합니다. 상태 메시지가 200ms 늦게 렌더링되면 테스트는 실패하고, 이런 실패는 간헐적으로 일어나므로 결국 불안정한 테스트(flaky test)가 됩니다. 웹 퍼스트 버전인 toHaveText와 toBeVisible은 조건이 충족될 때까지 기다립니다.
빠르게 구별하는 방법이 있습니다. 웹 퍼스트 어설션은 await를 붙여 쓰고 Locator나 Page를 받습니다. toBe, toEqual 같은 일반 matcher는 평범한 값을 받으며 절대 재시도하지 않습니다.
알아 두면 좋은 점
- 부정 조건도 재시도합니다.
await expect(locator).not.toBeVisible()은 요소가 사라질 때까지 기다립니다. - 어설션별 타임아웃. 전역 타임아웃을 늘리는 대신, 느린 단계 하나에만
toHaveText('Done', { timeout: 15_000 })을 지정하십시오. - 소프트 어설션.
expect.soft(...)는 실패를 기록한 뒤 테스트를 계속 진행하므로, 한 화면의 여러 필드를 확인할 때 편리합니다. - 커스텀 폴링.
expect.poll(() => fetchStatus()).toBe('ready')는 API 응답처럼 UI가 아닌 값에도 같은 재시도 동작을 적용합니다.