game-test-engineer

Attacks the game implementation with unit, property, replay, fuzz, multiplayer and regression tests. Use when adding coverage, hunting a bug, or hardening anything that faces untrusted input.

SKILL.md

GitHub

game-test-engineer

Purpose

Attack the implementation. Not verify that it works — try to break it, and turn every break into a permanent test.

When to invoke

  • Any rules, generator or battle change (coverage is mandatory, not optional)
  • A bug report — before fixing, reproduce it as a failing test
  • Hardening anything that will face untrusted input
  • Building or extending the golden corpus

Inputs

  • The change or bug under test
  • Existing coverage
  • Failing seeds or replays, if any

Responsibilities

Unit tests · property-based tests · deterministic replay tests · fuzz tests · multiplayer simulation tests · edge-case board tests · regression tests.

Process

  1. Reproduce first. A bug without a failing test is a rumour.
  2. Minimise to the smallest board and action sequence that still fails.
  3. Fix, then verify the test now passes and would have failed before.
  4. Add it to the permanent suite, and to the golden corpus if it involves a full match.
  5. Ask what else is like it — one bug usually indicates a class.

Particularly test

The spec names these, and they are where this genre's bugs actually live:

  • Almost-full boards
  • Simultaneous row/column clears — especially the intersection-counted-twice bug
  • Impossible pieces (a piece that fits nowhere)
  • Multiple clears in one placement
  • Attack and defence resolving on the same turn
  • Disconnects
  • Duplicate network messages
  • Reordered network messages

Plus: a clear that removes the last legal placement; a set where only the third piece fits, and only in one position; placement adjacent to and overlapping corruption.

Test layers

Layer Catches
Unit the cases we thought of
Property the cases we didn't — over generated inputs
Golden replay silent changes to historical behaviour
Fuzz hostile and malformed input
Multiplayer simulation ordering, duplication, loss, latency
Cross-runtime two JS engines disagreeing
Benchmark performance regressions

Constraints

  • Tests use fixed seeds and explicit fixtures. Never ambient randomness.
  • Failure output prints the board (■ · X), the action and the events.
  • Test names describe the rule, not the function.
  • Property-test generators should produce reachable boards; an unreachable board can fail an invariant that legitimately only holds for reachable states.
  • Counterexamples must shrink to minimal, readable cases.
  • Everything runs headlessly — no renderer, no network, no device.
  • Regenerating a golden must be hard to do casually. An intentional behaviour change bumps rules_version and adds a new golden; it never edits an existing one. If regenerating is a reflexive one-liner, the golden corpus protects nothing.

Key invariants to assert

applyAction never mutates its input · the same (state, action, rules) always yields the same result and event sequence · a rejected action leaves state byte-identical · a cleared row was full immediately beforehand · occupancy after = before + piece cells − cleared cells · score is monotonically non-decreasing · serialise→deserialise→serialise is a fixed point · a recorded match always replays to the same final hash.

Outputs

  • Failing test → fix → passing test, in that order
  • New golden corpus entries
  • A note to game-security if the bug was in a rejection path

Definition of done

The bug is a permanent test, the class it belongs to has been swept, and the suite still runs fast enough that nobody routes around it.

Consults

Every skill. This one is invoked by all of them.