Test environment checklist
Sixteen checks on the environment a suite runs in, rather than on the code it tests. The order follows what a failing suite costs you. Configuration is first because a variable that is set in one shell and absent in another produces a failure with nothing in the diff to explain it, and because a secret in a test environment is a real secret. The doubles come next, since a mock that was never wired in asserts nothing and reports success, which is the most expensive kind of green. Time is its own group because a suite that passes in one timezone and fails in another has no bug in it at all. The last group is order and concurrency, where a deterministic test fails because of what another test did or is doing at the same moment. Every check here was run against vitest 5.0.0 on Node 22.23.2, and the pages name the runner because the answers move between versions.
16 checksabout 172 min end to end
Configuration, before anything runs
- How to check if env variable exists
A guard that fails at startup with the full list beats one that fails inside a request, and unset and set-to-empty are different states that shells disagree about. - How to mock environment variables in vitest
A module that read the variable at import time cannot see one set in a hook, and every value is a string, so the obvious comparisons are never equal. - How to check config drift between environments
The example file, the real file and the keys the code reads are three sets, and a grep for direct reads misses destructuring and bracket access. - How to check for secrets in environment variables
A test-mode key is a real key when the sandbox holds real data, and deleting the file that held it leaves the value readable in the history. - How to check feature flags in test environment
A suite that never forces the flag tests whichever branch the default happens to select, and a config change silently moves it to the other one. - How to check seed data in test database
A seed that is not idempotent doubles rows on the second run, and a test that mutates seeded data hands the next test a different database.
Doubles, which fail by succeeding
- How to verify a mock was called
Asserting on a mock that was never wired in passes without testing anything, and recorded arguments are references, so the first call can report the last call's values. - How to reset mocks between tests
Clearing history, resetting the implementation and restoring the original are three different operations, and the runners disagree about which one a spy survives. - How to mock fetch in vitest
A plain-object stub passes until the code reads the response twice or checks a property the real one carries, and a stub on the global misses a reference captured at import. - How to spy on a function in jest
A spy on a function a module calls on itself never fires, which is the actual reason behind most reports that a spy does nothing. - How to test with a mock server
A stub that can only succeed tests half the code, and one that answers with a body the real service would never send makes the test pass for the wrong reason.
Time, which is environment and not code
- How to test with fake time
A fake clock that replaces the timers and not the date produces code that believes no time has passed, and a leaked clock fails a later file whose stack trace points elsewhere. - How to mock date in jest
An assertion built from the current time on both sides passes for the wrong reason and cannot fail, so freezing the clock is what makes the test able to detect anything. - How to run jest tests with a specific timezone
The same suite gives different answers in different zones, and how you set the zone is itself environment-dependent enough to change the result.
Order and concurrency
- How to check test isolation
A test can be green alone, red in its file and red in the suite for a third reason, and a seeded shuffle is what makes the dependency reproducible instead of intermittent. - How to detect parallel test interference
The failure count tracks the worker count rather than the code, and a suite can pass at full concurrency while writes to a shared file are being lost.
Take it with you
The file is the same list as Markdown checkboxes, ready to paste into a release ticket or a pull request description.
Ticks are kept in this browser only. They are not sent anywhere and other people do not see them.