跳转到内容
查看源码

回放测试

应用的测试是放在场景旁边的 .replay 文件:一行一步,# 开始注释,路径相对于回放文件。回放就是测试,框架也用它测试自己(docs/DECISIONS.md)。

终端窗口
entelechy replay examples/life/tests/blinker.replay
entelechy replay tests/*.replay --watch
entelechy player --replay examples/voxel/tests/voxel.replay

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.0
expect 11 9 = 1.0 0.85 0.45 0.06
expect 10 10 = 0.07 0.09 0.14
frame 0.1
expect 10 10 = 1.0 0.85 0.45 0.06
# Painting with the pointer makes cells live at the pointer.
pointer 20 15 down
frame 0.2
expect 20 15 = 1.0 0.85 0.45 0.06
pointer up
# Holding C clears everything.
key 67 down
frame 0.3
expect 20 15 = 0.07 0.09 0.14
key 67 up
# Reset restarts from the seed.
reset
frame 0.4
expect 11 9 = 1.0 0.85 0.45 0.06
$ entelechy replay examples/life/tests/blinker.replay
examples/life/tests/blinker.replay: ok (6 frames, 15 checks)

第一个场景的回放:

scene ../scene.esn
frame 0.0
expect count rings.result = 65536
expect 128 128 = 0.0 0.0 0.4
tests/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> 在窗口中播放回放。

协议的 compose 可以写 .replay(整段 text,在场景和它引用的 Kernel 存在之后)——Agent 修改世界时可以同时写下证明修改正确的测试,然后用 entelechy replay 运行。