Skip to content

Testing and debugging ​

Because gamekit never reads the wall clock and keeps simulation apart from drawing, most of a game can be tested in a console program. The testing family gives you the clocks and debug tools for it. Import them from gamekit/src/testing; importing other families adds no registry or per-frame callback.

ts
import { ComponentKey, Entity, PhaseSchedule, World } from "gamekit";
import { DebugTools, SimulationClock } from "gamekit/src/testing";

class Counter {
    n: int = 0;
}
const COUNTER: ComponentKey<Counter> = new ComponentKey<Counter>("counter");

const world: World = new World();
world.registerStore(COUNTER);
const e: Entity = world.createEntity();
world.put(e, COUNTER, new Counter());

const schedule: PhaseSchedule = new PhaseSchedule();
schedule.addPhase("simulate", [], true);
schedule.addSystem("simulate", (w: World, dt: float, tick: int): void => {
    w.getRequired(e, COUNTER).n += 1;
});

// A SimulationClock runs fixed ticks from elapsed time you feed it. No window, no wall clock.
const clock: SimulationClock = new SimulationClock(0.1, 8, (dt: float, tick: int): void => {
    schedule.run(world, dt, tick);
});
const ran: int = clock.advance(0.35);    // three whole ticks, the rest carries over
console.log("ticks run: " + ran + ", counter " + world.getRequired(e, COUNTER).n);

// DebugTools turns state into stable data for asserts and failure messages.
const before: string = DebugTools.canonicalSnapshot({ hp: 10, name: "slime" });
const changed: any = DebugTools.diff({ hp: 10, name: "slime" }, { hp: 7, name: "slime" });
console.log(before);
console.log(JSON.stringify(changed));
text
ticks run: 3, counter 3
{"hp":10,"name":"slime"}
{"changed":["hp"],"before":{"hp":10,"name":"slime"},"after":{"hp":7,"name":"slime"}}

Clocks you advance ​

ClockUse it for
SimulationClock(tickDuration, catchUpCap, tickWork)A fixed-step loop. advance(elapsed) runs whole ticks and carries the remainder; at most catchUpCap ticks per call. Also step(), singleStep(), pause(), resume(), setTimeScale(), interpolation.
PresentationClock()Variable time for presentation-side work, with pause and time scale.
ClockScheduler()Timed callbacks. schedule(delay, fn), scheduleEvery(period, fn), then advance(elapsed). Pass it wherever gamekit asks for a scheduler, such as effect durations and StateMachine.transitionAfter.
ScheduleOwnerA generation token: work scheduled with an owner is retired when the owner is disposed or reused from a pool.

In a game, the runtime's tick does this job (App.onTick, App.ticker, node tickers). These clocks stand in for it in tests.

DebugTools ​

Static helpers that return detached data. They never advance a clock, read input, load an asset or touch storage.

CallReturns
canonicalSnapshot(value)Sorted, stable JSON for a value. Good for comparing states.
diff(before, after)The top-level keys that changed, with both sides.
assertTranscript(actual, expected)Throws with a readable diff when two transcripts differ.
inspectWorld, inspectQuery, inspectPhases, inspectClock, inspectInputRouter, inspectScenes, inspectEffects, inspectAssets, inspectSavesA description of what each object owns and in what order.

DebugScenario ​

new DebugScenario(seed) records your game's step inputs with step(label, input). run(initial, apply, assertFailure?) replays them and returns either the transcript or the first failure, with the seed, the step, the input and before and after snapshots with a diff. minimize(stillFails) shrinks a failing scenario to the smallest set of steps that still fails.

DebugTrace ​

new DebugTrace(enabled = false, maxEntries = 128, redactor?, callback?) is a bounded log. While disabled, record returns at once and keeps nothing. Your optional redactor decides what is safe to keep.

Test fakes elsewhere ​

  • FakeAssetLoader (core) loads from memory and can fail or delay on purpose.
  • MemoryByteStorage and FaultInjectingByteStorage (save) keep saves in memory and fail on demand.
  • An IMusicBackend fake stands in for audio in MusicDirector tests.

See also the replay recipe.

Reference: SimulationClock, ClockScheduler, PresentationClock, DebugTools, DebugScenario, DebugTrace.