테스트 작성하기
테스트 작성하기 (Writing Tests)
Playwright 테스트는 크게 두 가지 동작으로 이루어져요. 어떤 액션을 수행하고, 그 결과로 **상태가 기대와 맞는지 단언(assert)**하는 거죠. 테스트를 직접 작성해 보기 전에, Playwright가 어떤 철학으로 테스트를 단순하게 만드는지 먼저 보면 좋아요. 액션을 수행하기 전에 그 요소가 조작 가능한 상태에 도달할 때까지 Playwright가 자동으로 기다려 줘서, 수동 대기나 경쟁 조건을 신경 쓸 필요가 없어요.
첫 테스트
테스트 파일 하나를 예시로 보면서 구조를 익혀 볼게요. test와 expect를 @playwright/test에서 가져와서, 페이지에 접속한 뒤 제목이 특정 문자열을 포함하는지 확인하는 단언을 넣은 모습이에요.
import { test, expect } from '@playwright/test';
test('has title', async ({ page }) => {
await page.goto('https://playwright.dev/');
// Expect a title "to contain" a substring.
await expect(page).toHaveTitle(/Playwright/);
});
test('get started link', async ({ page }) => {
await page.goto('https://playwright.dev/');
// Click the get started link.
await page.getByRole('link', { name: 'Get started' }).click();
// Expects page to have a heading with the name of Installation.
await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible();
});
VS Code에서 JavaScript로 작성한다면 각 테스트 파일 맨 위에 // @ts-check를 붙여 주면 자동 타입 체크를 받을 수 있어요.
액션
내비게이션
대부분의 테스트는 URL로 이동하는 것으로 시작해요. 페이지가 load 상태에 도달할 때까지 Playwright가 기다린 뒤 다음 단계로 진행해요.
await page.goto('https://playwright.dev/');
page.goto("https://playwright.dev/")
상호작용
요소를 조작하려면 먼저 그 요소를 찾아야 하는데, Playwright는 이때 Locators API를 사용해요. 로케이터는 페이지에서 요소를 찾아내는 방법 자체를 나타내며, 그 시점의 상태와 무관하게 항상 동작해요. 액션을 수행하기 전에도 요소가 조작 가능한 상태가 될 때까지 Playwright가 기다려 주니, 직접 대기 코드를 넣을 필요가 없어요.
// Create a locator.
const getStarted = page.getByRole('link', { name: 'Get started' });
// Click it.
await getStarted.click();
대부분은 한 줄로 합쳐 써요.
await page.getByRole('link', { name: 'Get started' }).click();
기본 액션
자주 쓰는 액션을 몇 가지 정리하면 이러해요. 전체 목록은 Locator API 문서에서 볼 수 있어요.
| 액션 | 설명 |
|---|---|
Locator.check |
체크박스에 체크 |
Locator.click |
요소 클릭 |
Locator.uncheck |
체크박스 체크 해제 |
Locator.hover |
요소에 마우스 호버 |
Locator.fill |
폼 필드에 텍스트 입력 |
Locator.focus |
요소에 포커스 |
Locator.press |
단일 키 누르기 |
Locator.setInputFiles |
업로드할 파일 선택 |
Locator.selectOption |
드롭다운에서 옵션 선택 |
단언
Playwright는 expect 함수 형태의 테스트 단언을 제공해요. expect(value)를 호출하고 기대를 반영하는 매처(matcher)를 고르면 돼요. async 매처는 기대 조건이 충족될 때까지 대기하기 때문에 테스트가 매끄럽고(flaky) 경쟁 조건에 취약하지 않아요. 예를 들어 이 코드는 페이지 제목에 "Playwright"가 들어갈 때까지 기다려요.
await expect(page).toHaveTitle(/Playwright/);
자주 쓰는 async 단언 몇 가지를 표로 정리했어요.
| 단언 | 설명 |
|---|---|
LocatorAssertions.toBeChecked |
체크박스가 체크됨 |
LocatorAssertions.toBeEnabled |
컨트롤이 활성화됨 |
LocatorAssertions.toBeVisible |
요소가 보임 |
LocatorAssertions.toContainText |
요소가 텍스트를 포함 |
LocatorAssertions.toHaveAttribute |
요소가 속성을 가짐 |
LocatorAssertions.toHaveCount |
요소 목록의 길이 |
LocatorAssertions.toHaveText |
요소가 텍스트와 일치 |
LocatorAssertions.toHaveValue |
입력 요소의 값 |
PageAssertions.toHaveTitle |
페이지 제목 |
PageAssertions.toHaveURL |
페이지 URL |
toEqual, toContain, toBeTruthy 같은 범용 매처로도 아무 조건이나 단언할 수 있어요. 이들은 이미 값이 준비된 상태에서 즉시 동기적으로 확인하므로 await 키워드를 쓰지 않아요.
expect(success).toBeTruthy();
테스트 격리
Playwright Test는 테스트 픽스처라는 개념에 기반을 두고 있으며, 대표적인 게 테스트에 전달되는 내장 page 픽스처예요. 페이지는 브라우저 콘텍스트 덕분에 테스트 간에 서로 격리돼요 — 마치 완전히 새로운 브라우저 프로필을 쓰는 것과 같죠. 같은 브라우저에서 여러 테스트가 돌아도 각 테스트는 항상 깨끗한 환경을 받아요.
import { test } from '@playwright/test';
test('example test', async ({ page }) => {
// "page" belongs to an isolated BrowserContext, created for this specific test.
});
test('another test', async ({ page }) => {
// "page" in this second test is completely isolated from the first test.
});
테스트 훅 사용하기
test.describe로 테스트 그룹을 묶고, test.beforeEach·test.afterEach로 각 테스트 전후에 실행되는 코드를 선언할 수 있어요. test.beforeAll·test.afterAll은 워커 하나당 전체 테스트 앞뒤로 한 번씩만 실행되고요. 아래처럼 describe 안에서 번거로운 준비 코드를 한곳에 모아 두면 각 테스트는 핵심만 남겨요.
import { test, expect } from '@playwright/test';
test.describe('navigation', () => {
test.beforeEach(async ({ page }) => {
// Go to the starting url before each test.
await page.goto('https://playwright.dev/');
});
test('main navigation', async ({ page }) => {
// Assertions use the expect API.
await expect(page).toHaveURL('https://playwright.dev/');
});
});