The AI-generated date test passes today and fails next week
You asked the agent to cover a subscription expiry. It wrote a unit test, ran it locally, reported green, and moved on. A week later CI goes red on that exact test. Nothing in the product changed. The test reads the real clock, so it only held under the date the agent happened to run on.
This is one of the gentlest failure modes an agent introduces: the test genuinely passed, the assertion looked correct, and the reviewer saw a green unit test and assumed determinism. A test that depends on the wall clock is not a deterministic test; it is a short-term prediction dressed up as coverage, and it quietly expires on its own schedule.
The agent cannot know the future date, and it rarely flags that its own test uses the current instant. It computes expiry from now(), compares against today's calendar, and the result agrees on the machine and the day it was written. The bug surfaces later, when time itself moves.
Why a clock-dependent test reads as correct
- It passes on the machine that writes it. The live clock matches the expected behavior at that instant, so green feels like proof the logic works rather than proof the logic works today.
- The assertion reflects real behavior under today's time. An expiry check that looks right under the current instant is easy to mistake for a durable test; the off-by-one lives in the future, not in the current run.
- Reviewers skim green and stop. A passing unit test carries the same visual weight regardless of whether it freezes time, so a clock read inside the test goes unnoticed.
- Some agents bake in a calendar literal. Rather than an offset, the expected value becomes a fixed date string for the week the test was written, narrowing the window to a handful of days instead of a condition that holds forever.
- Midnight and timezone drift hide the cause. A test that flips near midnight, or differs between machines in different zones, gets filed as flaky and quarantined instead of traced to the live clock.
What it looks like in the output
- The test calls
Date.now(),new Date(), ortime.Now()directly. The unit under test receives no injected clock, so every assertion anchors to the real current instant. - The expected expiry is computed as today plus N inside the test. The expectation itself moves when the clock moves, which is why the same code passes today and fails next week.
- A literal calendar date appears in the expected value. The agent hardcodes a specific day so the assertion passes only within a narrow window around writing time.
- The just-expired boundary uses the current instant. The "already expired" branch and the "still active" branch are chosen by the live clock, so moving time changes which case the test actually exercises.
- Green on the author's machine, red on a later day. The suite passes locally, passes CI the first few runs, then turns red on a date nobody changed in code.
The gate: freeze time and assert offsets
- Inject a clock into the unit under test. Pass
nowFnor a clock object instead of calling the system time inside the logic, so the test supplies a fixed instant rather than borrowing the real one. - Freeze time in the test. Pin
Date.now()or use a fake clock set to one known timestamp; every assertion derives from that fixed value. - Assert the offset, not the absolute date string. Check that expiry equals the pinned instant plus seven days, rather than comparing against a calendar literal that ages out.
- Test both sides of the boundary at the same pinned time. Cover one millisecond before expiry and one millisecond after under the identical fixed instant, so the live clock cannot quietly select which branch you exercise.
- Advance the fake clock deliberately. Move the pinned instant forward a week or a month in the test and confirm every assertion still predicts the outcome; this catches a time bomb before CI does.
Before you accept a green date test
- Does the test read the live clock, or receive an injected fixed
now? - Is the expected value an offset from a pinned instant, not a calendar literal or today plus N computed at runtime?
- Are both sides of the expiry boundary tested under the same pinned time?
- Can you advance the fake clock and still predict every assertion with no surprises?
A green date test today only proves the clock on the machine that ran it. Freeze time, assert the offset, and cover both sides of the boundary, so next week turns into a green suite rather than a red surprise.