불안정한 테스트 방지: Laravel 테스트에서 시간 고정

발행: (2026년 1월 10일 오전 03:34 GMT+9)
3 min read
원문: Dev.to

Source: Dev.to

Stop Flaky Tests: Laravel 테스트에서 시간 고정하기를 위한 표지 이미지

문제

내 로컬에서는 이 테스트가 정상적으로 실행됐지만, CI에서는 무작위로 실패했습니다:

public function test_order_item_cancel(): void
{
    $user = UserFixture::createUser();
    $this->actingAsFrontendUser($user);

    $order = OrderFixture::create($user);
    $orderItem = OrderItemFactory::new()->for($order)->for($user)->create();

    $response = $this->put(route('api-v2:order.order-items.cancel', ['uuid' => $orderItem->uuid]));

    $response->assertNoContent();

    $this->assertDatabaseHas(OrderItem::class, [
        'uuid' => $orderItem->uuid,
        'canceled_at' => Date::now(),
    ]);
}

때때로 테스트는 다음과 같은 오류를 발생시켰습니다:

Failed asserting that a row in the table [order_items] matches the attributes {
    "canceled_at": "2026-01-09T10:24:52.008406Z"
}.

Found: [
    {
        "canceled_at": "2026-01-09 12:24:51"
    }
].

처음엔 단순히 재시도했지만, The Flaky Test Chronicles VI를 읽고 나서 이것이 실제 버그인지 플레이키 테스트인지 조사해야 한다는 것을 깨달았습니다.

왜 이런 일이 발생하나요

Date::now()가 두 번 호출됩니다:

  1. 컨트롤러가 canceled_at을 설정할 때.
  2. 테스트가 값을 확인할 때.

밀리초 차이만 있어도 타임스탬프가 일치하지 않게 됩니다. CI 환경은 보통 로컬보다 느리기 때문에 이런 불일치가 더 자주 나타납니다.

해결 방법

요청을 보내기 전에 시간을 고정하면 컨트롤러와 테스트가 동일한 타임스탬프를 사용합니다.

// Option 1
$this->freezeTime();

// Option 2
$now = Date::now();
Date::setTestNow($now);

$response = $this->put(route('api-v2:order.order-items.cancel', ['uuid' => $orderItem->uuid]));

$this->assertDatabaseHas(OrderItem::class, [
    'uuid' => $orderItem->uuid,
    'canceled_at' => $now,
]);

$this->freezeTime()Date::setTestNow()를 테스트 라이프사이클에 맞게 감싸는 편리한 래퍼입니다. 시간을 고정하면 타임스탬프가 일치하고 테스트가 결정론적으로 동작합니다.

다른 방법

필드가 비어 있지 않기만 하면 된다면, canceled_atnull이 아님을 검증할 수 있습니다:

$this->assertDatabaseMissing(OrderItem::class, [
    'uuid' => $orderItem->uuid,
    'canceled_at' => null,
]);

최종 생각

테스트가 시간에 의존한다면 시간을 직접 제어하세요. 로컬에서는 통과하지만 CI에서 실패한다면 Date::setTestNow() 또는 $this->freezeTime()을 사용해 시간을 고정하십시오. 테스트를 결정론적으로 만들면 신뢰성과 안정성을 유지할 수 있습니다.

Back to Blog

관련 글

더 보기 »

API Laravel 배우기: 문제에서 솔루션까지!

한 번이라도 겪어본 적 있나요? Frontend React가 Backend Laravel에서 데이터를 가져오지 못했나요? > Postman이 응답 없이 계속 돌아가나요? 안심하세요, 당신만 그런 것이 아닙니다! > 많은 초보자들이 Laravel…