What to test, in priority order
Not everything needs a test. Test the things that matter most and are hardest to eyeball:
- Pure helpers (
clamp,aabb,lerp), fast, no dependencies, relied upon everywhere. - **Difficulty curve*: encode the fairness caps as assertions so they can't regress.
- **Scoring*:
addCoinalways adds 100;totalcounts coins;highonly grows. - **Collision*: the four-edge test for overlap and non-overlap.
- **Generation*: a spawned chunk never places a hazard in the safe zone; coins avoid hazards by the clearance.
Skip testing anything that just moves pixels around visually (like draw) unless you add expensive screenshot tests. Focus on the rules, not the rendering.
flowchart TD
A[Test strategy] --> B[Pure helpers]
A --> B2[Difficulty / fairness]
A --> B3[Scoring]
A --> B4[Collision]
A --> B5[Generation rules]
B --> C[Most bugs covered]
B2 --> C
B3 --> C
B4 --> C
B5 --> C
These five layers catch the bugs that actually matter: unfair difficulty, wrong scores, missed collisions, and impossible spawns.
Why games are worth testing
A common myth is that games can't be tested because they're "visual." But the interesting parts of a game are logic, not pixels:
- Is the score right? → test
addCoin. - Is the difficulty fair? → test
DIFFICULTYcaps. - Did the player touch the hazard? → test
aabb. - Is the spawn safe? → test generation rules.
Testing these means you can change the difficulty curve or the coin value **without fear*: a test suite tells you in seconds if you broke a rule. That's the real payoff: confidence.
The game ships with this exact suite in test/: files like score.test.js, physics.test.js, group13-solvability.test.js. Run them with a Node test runner; they need no browser. They turn "does this feel right?" into "the tests say yes."
Every cap in config.js has a matching test. That's the contract: the tests lock in fairness so nobody can accidentally make the game unfair again.