Skip to content
experience

The test that only failed on Tuesdays (yes, only Tuesdays)

Luis Treviño@luis_qa_mty

August 25, 2026 · 3 min read

ok this one took me 3 weeks and I need to share it because neta I still don't believe it.

Context: I do QA automation for a US insurance app, Playwright + TypeScript, around 900 e2e tests that run every night on CI at 2am Central. We had one test, renew policy shows correct premium, that started failing. Not every night. Some nights. Rerun, it pass. Classic flaky, we put it on the quarantine list and move on.

Then my team lead ask me to "please find the pattern, wey" (he didn't say wey, I add it). So I export 60 nights of results to a spreadsheet. And there it was. It failed on 8 nights. All 8 were Tuesdays. Every Tuesday, no exception, never any other day.

Suspect 1: timezone

Because it is always timezone. CI runs in UTC, the app thinks in America/Chicago, 2am Central is 7am UTC, same date. Not timezone. I was almost sad.

Suspect 2: something that runs on Tuesdays

I asked infra. Backups, cron jobs, staging reset. Nothing on Tuesday. Infra looked at me like I was crazy. Fair.

Suspect 3: the test itself

Finally I read the login helper, which I never read because "it works". It had this:

// spread load across test accounts so we don't get rate limited
const TEST_USERS = [
  'qa_sun@example.test',
  'qa_mon@example.test',
  'qa_tue@example.test',
  'qa_wed@example.test',
  'qa_thu@example.test',
  'qa_fri@example.test',
  'qa_sat@example.test',
]
const user = TEST_USERS[new Date().getDay()]

getDay() returns 0 for Sunday, so 2 is Tuesday. And qa_tue was the account a manual tester used 4 months ago to test policy cancellation. Her policy was cancelled. The renew screen added a reinstatement fee, so the premium was different. Only on Tuesdays, because the test only logged in as her on Tuesdays 🤣

Somebody wrote this 2 years ago to avoid rate limits, and nobody remember.

The fix

  • No shared accounts for e2e. Each test creates its own user and policy through the API in a fixture, and deletes it after. Maybe 2 seconds slower per test. I don't care.
  • Time is controlled, not real. Playwright has a clock API (1.45+), so tests that care about dates set it explicitly:
test('renewal premium on the anniversary date', async ({ page }) => {
  await page.clock.setFixedTime(new Date('2026-08-25T10:00:00-05:00'))
  await page.goto('/policies/renew')
  // ...
})
  • Timezone and locale fixed in the config, so nobody's laptop is "special":
// playwright.config.ts
use: {
  timezoneId: 'America/Chicago',
  locale: 'en-US',
},
  • And the most important: the quarantine list now has an owner and an expiry date for every test. If a test sits there more than 2 weeks, it goes to standup. Flaky is not a root cause, is a symptom.

Moral: when a test is flaky, export the history and look at the days. Look at the time. Look at the user. Not everything is a race condition, sometimes is just a Tuesday.

Ahorita I am checking every new Date() in our helpers. There are 41. Pray for me.

Get the best of #flaky_test_society weekly

One email each Monday with the most useful posts. No spam; unsubscribe in one click.

Comments

15

Sign in to join the conversation.

Sign in to comment
Siobhan O'Rourke@siobhan_tests#2 in Flaky Test Society
Exporting the history and pivoting by weekday is SUCH an underrated move. I once found a test that failed only on the 31st because a fixture did "current month + 1" with the same day, and there is no 31 September. Great writeup Luis.
9 net votes
Luis Treviño@luis_qa_mty#1 in Flaky Test Society
jajaja the 31st one is so evil. JavaScript just moves it to October 1 and says nothing 🤣
4 net votes
Sofía Ramírez@sofi_dev_mx#7 in Flaky Test Society
Wey qué bárbaro, 3 semanas por un getDay() 😅 pero qué buen detective. Lo voy a compartir en codigo_en_espanol
12 net votes
Luis Treviño@luis_qa_mty#1 in Flaky Test Society
compártelo, que la gente aprenda a no usar cuentas compartidas jajaja
5 net votes
Iryna Melnyk@iryna_qa#3 in Flaky Test Society
Shared test accounts are the root of so much evil) We had one account "qa_main" that every team used. Somebody changed its language to Polish and 200 tests failed from the first time next morning. Fixture per test is the only way.
5 net votes
Marcus Johnson@marcus_oncall#5 in Flaky Test Society
Good find. Bonus round: also check what the CI runner's clock thinks the date is. We had a self-hosted runner with a dead CMOS battery that booted into 2019 after every power cut. Tests that used real time had a very bad week.
5 net votes
Luis Treviño@luis_qa_mty#1 in Flaky Test Society
no manches, 2019 😂 that one is worse than mine
2 net votes
Camilo Restrepo@camilo_parce#7 in Flaky Test Society
Me pasó con un test que fallaba solo en quincena 😂 el fixture calculaba fechas de pago. Buen post Luis
6 net votes
Frank Ostrowski@frank_cpp98#10 in Flaky Test Society
A function where Sunday is zero, in a language where January is also zero. Your language did this to you. Regards.
5 net votes
Luis Treviño@luis_qa_mty#1 in Flaky Test Society
frank for once I am agree with you, zero based months are a war crime. but the human who wrote the helper also did this to me
2 net votes
Trần Phương Thảo@thao_qa#4 in Flaky Test Society
I very agree with "flaky is not root cause, is symptom". I will print it and put on my desk 🐞 Also thank you for the page.clock example, I did not know it exist
5 net votes
Sayan Mukherjee@bong_bugs#6 in Flaky Test Society
qa_tue had one job. ONE JOB. and she was cancelled 4 months ago. ki bolbo, most relatable user in this whole story 🐟
5 net votes
Priya Rawat@priya_tests#10 in Flaky Test Society
sahi baat. test data khud banao, shared account pe bharosa mat karo 🙂 great story
7 net votes
Sam Whitaker@segfault_sam#7 in Flaky Test Society
i hate mondays is out. i hate tuesdays is in
3 net votes
佐藤はるか Haruka@nekomata_games#10 in Flaky Test Society
this is the scariest story I read this month (゜ロ゜) my save system uses new Date()... going to check now
10 net votes