CI에서 플레이라이트 테스트 안정화: 의존성 프로젝트와 웹 우선 검증
플레이라이트의 체인형 의존성은 불안정한 환경에서 테스트 실행을 방지해 CI 자원을 절약하고, 오류 발생률을 줄입니다.
먼저 API를 통해 인증을 수행하고, 저장 상태를 유지합니다. 이후 건강 상태 확인을 통해 API 가용성을 검증합니다. 이 과정이 완료된 후에야 메인 UI 테스트가 실행됩니다.
글로벌 세팅보다 우수한 점:
- 네트워크 요청, 스크린샷, 콘솔 로그 포함 전부의 트레이스 기록 가능.
- 즉시 실패: 설정 단계에서 실패하면 의존 프로젝트는 즉시 중단됩니다.
- 격리성:
npx playwright test --project=auth-setup로 개별 단계를 독립적으로 테스트할 수 있습니다.
playwright.config.ts 내 구성 예시:
export default defineConfig({
projects: [
{
name: 'auth-setup',
testMatch: /.*\.auth\.setup\.ts/,
},
{
name: 'healthcheck',
testMatch: /.*\.health\.setup\.ts/,
dependencies: ['auth-setup'],
},
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
dependencies: ['healthcheck'],
},
],
});
API 기반 인증은 설정 시간을 극도로 단축합니다: UI 로그인에 2~5초가 걸리는 반면, POST 요청은 50~100ms면 충분합니다.
auth-setup 테스트 예시:
test('setup', async ({ request }) => {
await request.post('/api/login', { data: { user, pass } });
await request.storageState({ path: '.auth/user.json' });
});
의존성 그래프는 병렬 테스트 실행 시 레이스 조건을 제거합니다.
로케이터를 현명하게 선택하기
로케이터 선택은 UI 변경에 대한 테스트 강건성에 직접적인 영향을 미칩니다. 목적에 따라 분리하세요: 액션에는 getByTestId, 검증에는 getByRole 또는 getByLabel을 사용하세요.
최적의 실천 방법:
- 액션(클릭, 입력):
page.getByTestId('add-to-cart-button').click()— 텍스트나 스타일과 무관합니다. - 텍스트/상태 검증:
expect(page.getByRole('heading')).toHaveText('내 계정'). - 입력 필드:
page.getByLabel('이메일').fill('[email protected]'). - 카운터:
expect(locator).toHaveText('3').
CSS 선택자는 최후의 수단으로만 사용하세요. 팀원들에게 올바른 로케이터 사용법을 교육하면 스케일링 시 10배 이상의 효과를 얻을 수 있습니다.
웹 우선 검증 vs 불안정성
await loc.isVisible() 같은 스냅샷 검사는 레이스 조건에 취약합니다. 폴링 기반의 웹 우선 검증은 안정성을 보장합니다.
검증 비교표:
| 검사 항목 | 스냅샷(대기 없음) | 웹 우선(폴링) |
|----------|------------------|--------------|
| 가시성 | await loc.isVisible() | expect(loc).toBeVisible() |
| 텍스트 | await loc.textContent() | expect(loc).toHaveText('문자열') |
| 개수 | await loc.count() | expect(loc).toHaveCount(3) |
| 속성 | await loc.getAttribute('href') | expect(loc).toHaveAttribute('href', '/path') |
| 체크박스 | await loc.isChecked() | expect(loc).toBeChecked() |
| 상태 | await loc.isEnabled() | expect(loc).toBeEnabled() |
폴링은 100ms 간격으로 재시도하며, 일시적인 UI 깜빡임을 무시합니다.
하이드레이션 및 force: true
SSR/SSG 앱에서는 서버 렌더링 마크업은 존재하지만, JS 핸들러가 아직 연결되지 않은 경우 하이드레이션 불일치가 발생합니다.
하이드레이션 마커 대기:
await page.waitForSelector('.hydrated', { state: 'attached' })await expect(page.locator('#global-loader')).toBeHidden()
force: true는 동작 가능성 검사를 비활성화합니다(가시성, 안정성, 활성화 여부, 이벤트 수신). 이로 인해 테스트는 순수 DOM 스크립트처럼 작동합니다. 파일 입력과 같은 특수 사례에만 적합하며, 반드시 주석을 함께 작성해야 합니다.
핵심 요약
- 의존성 프로젝트는 의존성 그래프를 구축해 준비되지 않은 환경에서 테스트가 실행되는 것을 막습니다.
- 웹 우선 검증은 폴링을 통해 레이스 조건으로 인한 불안정성의 80%를 제거합니다.
- 로케이터 역할 분리는 UI 리팩토링에 대한 강건성을 높입니다.
- API 기반 인증은 UI 로그인보다 설정 속도를 20~50배 빠르게 합니다.
- 트레이스는 스크린샷보다 CI에서 실패 원인을 파악하는 데 더 풍부한 맥락을 제공합니다.
— Editorial Team
아직 댓글이 없습니다.