Acceptance tests

Optional

An acceptance test turns one important promise of your design into a check the finished game must pass. The builder, the person, team or AI that turns your package into a game, reports whether each test passed. You say what must be true, not how to program it.

A test is a heading that starts with AT- and a number, immediately followed by one JSON block marked test. Tests are written in 05-build-plan.md, next to the build stage they belong to. Any explanation goes after the block. The numbers go up in document order, and a deleted test's number is never used again.

05-build-plan.md, under the heading AT-4: Alarm on sight

{
  "type": "scenario",
  "given": "a guard on patrol with the player inside its view cone",
  "when": "the player stays visible for alarm.spot_seconds",
  "then": ["the guard raises the alarm", "every other guard on the floor starts searching"],
  "diagnostics": ["visibility-timeline", "guard-state-after"]
}

Tests come in two kinds. A scenario is one situation. A general test is a promise about many cases. This one is a scenario. given is the starting situation, when is what happens, and then lists what must be true afterwards. Each can be one sentence or a list. diagnostics names the evidence a test run should keep, so a failure can be understood.

Names like alarm.spot_seconds inside a test are instructions for whoever runs it. The validator (the checking tool) does not check that they exist.

Most tests are scenarios. Write a general test when the promise is about many cases. The same stealth game generates its floors, and this promise is about all of them. scope says which cases, in your own words. holds says what must be true for all of them. seeds names the random sequences that generate the cases, so a failure can be reproduced.

05-build-plan.md, checking every generated floor of the same game

{
  "type": "general",
  "scope": "every floor generated at default tuning",
  "holds": "every guard's patrol route reaches every room on its floor",
  "seeds": ["patrol-routes-12"],
  "diagnostics": ["sample-seed", "floor-layout", "unreached-room"]
}

A general test can be checked over every case in its scope or over a sample. If the promise says "never" or "always", a sample is not enough. Only a check of every case can support it. The builder's report of the build says which general tests were sampled. When a test passed and is not listed as sampled, the report says it was checked over every case.

When to add tests#

Tests are optional, but 05-build-plan.md is still required for its build stages. One case needs a test: a measured color, contrast or timing promise in art direction must be covered by one. The Palette and color promises chapter shows how.

Without tests, no check can show that a build passed. The report of a build from such a package is not verified: it can be a valid report, but it never counts as a passing build. Tests the builder writes on their own do not change that. Add tests when you want builds checked against your design, starting with the promises a wrong build would break.

What to test#

Write tests for what a machine can check. A test that needs a person watching cannot be checked or run again, so every build reports it as not-run. While your package has such a test, no build counts as a passing build. Put a quality like "reads well at play speed" in Art direction instead, as a must-keep entry or in your presentation prose.

A balance test works best when it checks your intent in broad terms, such as "no single unit wins every matchup". Be careful with a test that says exactly who wins a match between scripted players (players run by a fixed program). Such a test can lead the builder to tune the game for that one scripted match instead of making it fun to play.

What the builder reports#

The builder's report of a build lists every test that did not pass, with a reason and one of three words:

  • failed: the test ran completely, and the build did not pass it;
  • partial: the test could be run only in part;
  • not-run: the test did not run. A test that needs a person watching is always not-run, and the reason says so.

Every test that is not listed passed. When the report is valid and every test passed, the build is conforming. When a valid report lists any test, the build is incomplete. The What validation proves chapter explains how the validator checks that report.

Full rules: OpenGDD specification, §6.

← Tuning · All chapters · Collections →