Replay tests
An application’s tests are .replay files next to its scene, one step a line, # a comment, paths relative to the replay file. A replay is a test; the framework tests itself (docs/DECISIONS.md).
entelechy replay examples/life/tests/blinker.replayentelechy replay tests/*.replay --watchentelechy player --replay examples/voxel/tests/voxel.replayA real example
Section titled “A real example”examples/life/tests/blinker.replay (excerpt):
scene blinker.esn
# The seed holds a horizontal blinker at (10..12, 10). The first frame steps it# once, so it stands vertical; the second frame lays it flat again.frame 0.0expect 11 9 = 1.0 0.85 0.45 0.06expect 10 10 = 0.07 0.09 0.14frame 0.1expect 10 10 = 1.0 0.85 0.45 0.06
# Painting with the pointer makes cells live at the pointer.pointer 20 15 downframe 0.2expect 20 15 = 1.0 0.85 0.45 0.06pointer up
# Holding C clears everything.key 67 downframe 0.3expect 20 15 = 0.07 0.09 0.14key 67 up
# Reset restarts from the seed.resetframe 0.4expect 11 9 = 1.0 0.85 0.45 0.06$ entelechy replay examples/life/tests/blinker.replayexamples/life/tests/blinker.replay: ok (6 frames, 15 checks)The first scene’s replay:
scene ../scene.esn
frame 0.0expect count rings.result = 65536expect 128 128 = 0.0 0.0 0.4tests/rings.replay: ok (1 frames, 2 checks)Every line
Section titled “Every line”| Form | What it does | Example |
|---|---|---|
scene <path> |
the scene to test, relative to the replay file; required | scene ../scene.esn |
library <path> |
Kernels beyond the scene’s use |
library ../kernels/ |
allow file.write <dir> | allow file.delete <dir> |
lets outputs write (or remove and rename) files under the directory; what they write is kept for the run and never reaches the disk, so every run starts from the same files | allow file.write ../laws/ |
alike |
its checks hold two forms of one computation equal word for word, true only where every Kernel rounds alike, so --round-apart leaves it out |
alike |
frame <seconds> [to <seconds> every <seconds>] |
evaluates a frame at this session time; with to and every, one at each step, both ends included |
frame 0.0, frame 0.1 to 2.0 every 0.1 |
settle |
waits for every async run to land |
settle |
pointer [<x> <y>] [down | up] |
moves the pointer, in the output’s pixels from its top left (what pointer() reads), and presses or releases it |
pointer 20 20 down, pointer up |
button <name> down | up |
left, right, middle, or a pad’s south, east, west, north, l1, r1, l3, r3, start, select | button right down |
stick left | right | triggers <x> <y> |
a pad’s axis pair | stick left 0.5 -1 |
pads <count> |
pads connected from here on, what pads() reads |
pads 1 |
wheel <x> <y> |
the scroll for the next frame only | wheel 0 -1 |
window <w> <h> [<scale>] |
the window in pixels (window()) and its scale, one when not given |
window 240 135 |
type "<text>" |
characters typed, what typed() reads next frame (32 a frame, the rest after); \", \\, \n, \t inside the quotes |
type "你好, Quill" |
clipboard "<text>" |
the clipboard holding this text from here on, what an input = clipboard reads |
clipboard "from elsewhere" |
key <code> down | up |
a key by the browser’s code, as key() reads it: letters and digits uppercase ASCII, space 32, enter 13, arrows 37–40, the rest in help key |
key 67 down |
reset [<node.port>] |
forgets every node’s committed state, or one port’s | reset, reset step.result |
param <name> <literal> |
sets a graph parameter | param exposure 1.5 |
expect <x> <y> = <r> <g> <b> [<tolerance>] |
the picture’s color at x y from its top left, channels 0 to 1; tolerance 0.01 by default | expect 11 10 = 1.0 1.0 1.0 |
expect <node.port[i][.field]> = <value>... [<tolerance>] |
an element of a node’s output or a field of it: ints and bools exactly, floats and vectors within the tolerance; i counts along the Field, x fastest, then y, then z |
expect step.result[0].score = 1 |
expect <node.port[i][.field]> < | <= | > | >= <number>... |
every component past a bound | expect fall.result[0].speed > 2.5 |
expect count <node.port> = <n> |
how many elements a node’s output holds | expect count ground.result = 6889 |
expect placed <node> main | ordered |
where a node runs: the main backend, or ordered work off it | expect placed ring main |
show <node.port[i][.field]> |
prints an element after the last frame; checks nothing | show step.result[0] |
The grammar is also in Class reference · Replay syntax.
Running
Section titled “Running”- Replays run together share their backends, documents and compiled Kernels, faster than one by one.
--watchplays again only the replays a change reaches, each computing only what changed.--round-apartruns each replay three ways, some Kernels rounding as another device might: a failure is a value two Kernels each compute and must hold equal — compute it in one.--outrecords a replay’s frames asrenderdoes.- The Player’s
--replay <file>plays one in the window.
Agents and tests
Section titled “Agents and tests”The protocol’s compose writes a .replay (whole, by text, once the scene and Kernels it names exist) — an agent changing a world can write the test proving its change, then run it with entelechy replay.

