시간에 기대는 화면은 시험이 시간을 쥔다
마감·만료·자동 갱신을 실제로 기다리지 않는다. 브라우저는 page.clock, 서버의 「지금」은 주입한 시계, 배경 주기 작업은 「한 번 돌기」로 부른다.
마감 경고, 토큰 만료, 자동 갱신처럼 시간이 지나야 바뀌는 화면을 시험하면서 그 시간을 실제로 기다리거나 고정 sleep으로 맞추면, 시험이 느리고 기계 상태에 따라 흔들린다.
원인은 시간이 시험 밖에 있다는 것이다. 브라우저 타이머, 서버의 현재 시각, 배경 작업의 주기가 모두 시험이 손댈 수 없는 곳에 있다.
세 곳 모두 시험이 쥐게 만든다.
- 브라우저 타이머: Playwright
page.clock으로 설치하고 앞으로 민다. - 서버의 「지금」: 코드 곳곳에서 현재 시각을 직접 부르지 말고, 주입할 수 있는 시계 객체에서 받는다. 시험은 시계를 바꿔 끼운다.
- 배경 주기 작업: 시험에서는 주기를 끄고 「지금 밀린 일을 바로 한 번 처리」하는 함수나 내부 끝점을 부른다. 이 한 번 돌기는 시간을 앞당기지 않는다. 지금 시점에 이미 처리할 일을 주기를 기다리지 않고 처리할 뿐이다.
import { test, expect } from '@playwright/test';
test('마감 5분 전이면 경고가 뜬다', async ({ page }) => {
await page.clock.install({ time: new Date('2026-01-01T09:00:00') });
await page.goto('/tasks/1'); // 마감이 10:00인 작업
await page.clock.fastForward('55:00');
await expect(page.getByText('마감 5분 전')).toBeVisible();
});
from datetime import datetime, timezone
class Clock:
def now(self) -> datetime:
return datetime.now(timezone.utc)
class FixedClock(Clock):
def __init__(self, at: datetime) -> None:
self.at = at
def now(self) -> datetime:
return self.at
고정 시간 대기(sleep, 고정 timeout)는 시험 어디에도 두지 않는다.