Testing a game

An agent can play a game the way a player does, and check what happened.

Press keys

input.set presses or lets go of a key, a mouse button or a gamepad control. It stays that way until set again.

{"command": "input.set", "binding": "W", "value": true}
{"command": "play.run", "seconds": 1.5}
{"command": "input.set", "binding": "W", "value": false}

For a stick, give a number from -1 to 1:

{"command": "input.set", "binding": "Gamepad LeftX", "value": 0.5}

input.release_all lets go of everything.

Let time pass

play.run takes frames or seconds. It enters play mode if needed and stays in it. It returns what the game logged meanwhile and how many script errors there were:

{"ok": true, "result": {"frames": 90, "log": [{"level": "INFO", "text": "[App] Collected 1 of 10"}], "script_errors": 0}}

Time advances in steps of 1/60 second without waiting for the clock, so a run gives the same result every time.

Read the game's state

lua.run can reach into any script:

{"command": "lua.run", "code": "local g = Scene.FindByName('Game'):GetScript('Game'); print('score ' .. g.Score)"}

It can also set things up, such as placing an enemy in front of the player before testing that shooting works.

Look at it

{"command": "screenshot", "path": "/tmp/play.png"}

Then open the image. A passing check does not prove the picture is right.

A whole test

This plays the third person template: walks forward for a second and checks the player moved.

{"command": "play.run", "frames": 20}
{"command": "input.set", "binding": "W", "value": true}
{"command": "play.run", "seconds": 1}
{"command": "input.release_all"}
{"command": "lua.run", "code": "local z = Scene.FindByName('Player').Position.z; print(z < 4.5 and 'walk ok' or 'walk failed at ' .. z)"}
{"command": "play.stop"}

The files in Tests/commands/ in the repository are tests of this kind, run by ctest.

Testing the editor's own window

For what a person does with the editor's window, --ui-script feeds it a scripted mouse and keyboard:

./build/Cairn-Editor/Cairn-Editor MyGame/MyGame.cairnproject --hidden --frames 40 \
  --ui-script "5:click 946,240; 15:key F" --expect-selected Crate --screenshot out.png

Each step is frame:action. The actions are click x,y, rclick x,y for the right button, move x,y, type text, clear (select all the text in the focused field) and key Name. Positions are in window units.

--expect-selected fails the run unless that entity is selected at the end. A hidden editor never starts another program: it logs what it would have opened.