Identify uncontrolled inputs
List anything that can vary between runs: random enemy positions, elapsed time, animation frame timing, a saved high score, viewport dimensions, and sequence of user inputs. Decide which variables matter to the behavior under test. For a collision check, use a fixed enemy location and a known player start. For a spawn-pattern check, control the random sequence but test several selected seeds so one setup does not hide a bad pattern.
Control time without freezing player behavior
For a timer rule, provide an explicit starting time and check what happens at a meaningful boundary, such as three seconds remaining and exactly zero. For frame-based movement, compare the same elapsed duration instead of the same number of rendered frames. MDN notes that requestAnimationFrame callback frequency generally follows display refresh rate and callbacks are paused in most browsers for hidden tabs; animation code should therefore use its timestamp or another time source when calculating progress.
Questions about deterministic game tests
Does deterministic testing mean removing random gameplay?
No. It means controlling randomness in selected tests to compare behavior. You can still run separate exploratory tests across varied seeds to inspect the game’s range.
Why can a test pass locally and fail in a browser run?
Different timing, viewport, saved state, or random sequence can alter the setup. Record those conditions and control the ones relevant to the behavior being checked.