debugtypescriptnoneMajor
Flaky Test Debugging: Root Causes and Fixes
Viewed 0 times
flaky testsrace conditionasync testingfake timerstest orderingrandomize
Error Messages
Problem
Tests pass most of the time but occasionally fail without code changes. Flaky tests erode trust in the test suite and slow down CI.
Solution
Identify and fix the root cause — flaky tests almost always have a deterministic root cause.
// Cause 1: Race conditions — async code not properly awaited
// BAD:
test('loads user', () => {
render(<UserProfile />);
expect(screen.getByText('Alice')).toBeInTheDocument(); // Races with fetch!
});
// GOOD:
test('loads user', async () => {
render(<UserProfile />);
expect(await screen.findByText('Alice')).toBeInTheDocument();
});
// Cause 2: Time-dependent tests
// BAD:
expect(new Date().getFullYear()).toBe(2024); // Fails in 2025
// GOOD: use fake timers
vi.useFakeTimers();
vi.setSystemTime(new Date('2024-06-15'));
// Cause 3: Random data without seed
// BAD:
const id = Math.random(); // Different each run
// GOOD: deterministic test data
const id = 'test-user-1';
// Cause 4: Test ordering dependency
// Run tests in random order to surface:
// jest --randomizeWhy
Flaky tests are caused by external non-determinism: time, randomness, async timing, test ordering, or shared state. Each has a specific fix.
Gotchas
- Adding retry logic to flaky tests hides the problem — always fix the root cause.
- Use '--runInBand' to run tests serially to surface ordering dependencies.
- Network calls in tests without MSW or similar mocking are inherently flaky.
Revisions (0)
No revisions yet.