回放测试
应用的测试是放在场景旁边的 .replay 文件:一行一步,# 开始注释,路径相对于回放文件。回放就是测试,框架也用它测试自己(docs/DECISIONS.md)。
entelechy replay examples/life/tests/blinker.replayentelechy replay tests/*.replay --watchentelechy player --replay examples/voxel/tests/voxel.replay一个真实的例子
Section titled “一个真实的例子”examples/life/tests/blinker.replay(节选):
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)第一个场景的回放:
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)| 写法 | 作用 | 示例 |
|---|---|---|
scene <path> |
要测试的场景,相对于回放文件;必需 | scene ../scene.esn |
library <path> |
场景 use 之外的 Kernel |
library ../kernels/ |
allow file.write <dir> | allow file.delete <dir> |
允许输出写入(或删除、重命名)该目录下的文件;写入只保留在本次运行中,不会落盘,所以每次运行都从相同的文件开始 | allow file.write ../laws/ |
alike |
断言同一计算的两种形式逐字相等——只有所有 Kernel 舍入相同时才成立,所以 --round-apart 会跳过它 |
alike |
frame <seconds> [to <seconds> every <seconds>] |
在该会话时间求值一帧;带 to 与 every 时按步长求值多帧(首尾都包含) |
frame 0.0、frame 0.1 to 2.0 every 0.1 |
settle |
等待所有 async 运行完成 |
settle |
pointer [<x> <y>] [down | up] |
移动指针(输出像素,从左上角起,即 pointer() 读取的值),按下或松开 |
pointer 20 20 down、pointer up |
button <name> down | up |
left、right、middle,或手柄的 south、east、west、north、l1、r1、l3、r3、start、select | button right down |
stick left | right | triggers <x> <y> |
手柄的一对轴 | stick left 0.5 -1 |
pads <count> |
此后连接的手柄数,即 pads() 读取的值 |
pads 1 |
wheel <x> <y> |
仅下一帧的滚动 | wheel 0 -1 |
window <w> <h> [<scale>] |
窗口像素尺寸(window())与缩放,默认 1 |
window 240 135 |
type "<text>" |
输入的字符,下一帧由 typed() 读取(每帧 32 个,其余顺延);引号内支持 \"、\\、\n、\t |
type "你好, Quill" |
clipboard "<text>" |
此后剪贴板中的文本,即输入 = clipboard 读取的值 |
clipboard "from elsewhere" |
key <code> down | up |
按浏览器键码,即 key() 读取的值:字母数字为大写 ASCII,空格 32,回车 13,方向键 37–40,其余见 help key |
key 67 down |
reset [<node.port>] |
忘掉所有节点(或一个端口)已提交的状态 | reset、reset step.result |
param <name> <literal> |
设置图参数 | param exposure 1.5 |
expect <x> <y> = <r> <g> <b> [<tolerance>] |
图片在 x y(左上角起)处的颜色,各通道 0–1;默认容差 0.01 | expect 11 10 = 1.0 1.0 1.0 |
expect <node.port[i][.field]> = <value>... [<tolerance>] |
节点输出的一个元素或其字段:整数和布尔精确比较,浮点和向量在容差内;i 沿 Field 计数,x 最快,然后 y、z |
expect step.result[0].score = 1 |
expect <node.port[i][.field]> < | <= | > | >= <number>... |
每个分量超过某个界 | expect fall.result[0].speed > 2.5 |
expect count <node.port> = <n> |
节点输出的元素数 | expect count ground.result = 6889 |
expect placed <node> main | ordered |
节点在哪里运行:会话主后端,或主后端之外的有序工作 | expect placed ring main |
show <node.port[i][.field]> |
在最后一帧后打印输出的一个元素;不做检查 | show step.result[0] |
完整语法也在类参考 · 回放语法。
- 一起运行的回放共享后端、文档和已编译的 Kernel,比逐个运行更快。
--watch只重放修改影响到的回放,每个只重新计算变化的部分。--round-apart以三种方式运行每个回放,让部分 Kernel 像另一种设备那样舍入:失败说明两个 Kernel 各自计算了一个必须相等的值——应该只在一处计算它。--out像render一样录制回放的帧。- Player 的
--replay <file>在窗口中播放回放。
Agent 与测试
Section titled “Agent 与测试”协议的 compose 可以写 .replay(整段 text,在场景和它引用的 Kernel 存在之后)——Agent 修改世界时可以同时写下证明修改正确的测试,然后用 entelechy replay 运行。

