evidence-driven-testing
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseEvidence-Driven Testing
证据驱动测试
Record annotated proof of behavior, then attach it to the PR and tracker issue.
The recording is the capture of you testing the app via computer use: start the
recorder, then drive the app yourself — click, type, navigate — through each
test target. Every action in the video is the test being performed live; the
recording has no value as evidence unless it shows that interactive session.
If the harness has no computer-use tools but a GUI exists, drive the app with
instead (see below) — it is still your live session.
cua-driverThe bundled recorder, , captures the display with FFmpeg
on Linux, macOS, and Windows, timestamps each annotation you add while
testing, burns them into the video on stop, and verifies the result with
ffprobe. It writes , , and into the
session folder.
scripts/evidence.pyevidence.mp4report.mdmanifest.json记录带标注的行为证明,然后将其附到 PR 和跟踪 issue 上。
录制内容是你通过 computer use 测试应用的过程:先启动录制器,然后亲自操作应用——点击、输入、导航——逐一完成每个测试目标。视频中的每个操作都是实时执行的测试;除非录制内容展示了这一交互会话,否则它作为证据没有任何价值。
如果测试框架没有 computer use 工具,但存在 GUI,请改用 驱动应用(见下文)——这仍然是你实时进行的会话。
cua-driver内置录制器 使用 FFmpeg 在 Linux、macOS 和 Windows 上捕获显示器,为测试期间添加的每条标注添加时间戳,停止录制时将其烧录到视频中,并使用 ffprobe 验证结果。它会将 、 和 写入会话文件夹。
scripts/evidence.pyevidence.mp4report.mdmanifest.jsonInputs
输入
- Test targets (required): The behaviors/flows to verify, phrased as testable statements.
- PR / issue (optional): Where to post the evidence. If omitted, deliver to the requester only.
- 测试目标(必填):需要验证的行为/流程,以可测试陈述的形式表述。
- PR / issue(可选):发布证据的位置。如果省略,则仅将证据交付给请求方。
The recorder
录制器
EVIDENCEscripts/evidence.py~/.claude/skills/evidence-driven-testing/scripts/evidence.py-
Check first:— verifies
python3 $EVIDENCE doctor,ffmpeg,ffprobe, and thelibx264filter (ass), then which screen-capture source works on this machine (readyand the sourcecapture_readywill pick). Exits non-zero only when the toolchain is missing; readautobefore recording.capture_ready -
Platforms (picks the first available):
--source autoOS Source Needs Linux X11 / XWayland (x11grab)x11setDISPLAYLinux Wayland (wf-recorder)waylandset,WAYLAND_DISPLAYon PATH, and a compositor confirmed to support wlr-screencopy — either a known wlroots one (Sway, Hyprland, river, Wayfire, labwc, dwl, niri) or verified viawf-recorder. GNOME and KDE Wayland are not capturable this way;wayland-infosays so. Usedoctorthrough XWayland for X11 apps, or a fallback recorder.x11still forces it--source waylandmacOS avfoundationScreen Recording permission granted to the terminal / agent host app; lists screen indexes fordoctor--screen-indexWindows gdigrabany standard ffmpeg build; for process checkspowershellCapture is the full screen by default;and--geometry WxHcrop a region on x11, wayland, and gdigrab. XWayland only sees X11 windows, so prefer the--offset X,Ysource when the app under test is Wayland-native.wayland -
Crash-safe raw capture: the raw recording is MPEG-TS (), so if the recorder is killed hard or crashes, what was captured still probes and renders.
raw.tsremuxes or re-encodes it into a standardstop.evidence.mp4 -
How stopping works: on Linux the recorder is signalled through a pidfd. On macOS and Windowslaunches a small supervisor process that owns the ffmpeg child, and
startasks it (viastopin the session folder) to interrupt, then terminate, then kill; it writesstop.requestwhen done. Nothing ever signals a bare PID, so a recycled PID can't be hit. If the supervisor dies while the recorder is still running,recorder-exit.jsonrefuses and tells you which PID to stop by hand. If it died before it could even record which process it started,stopstays blocked until you have checked for a stray recorder yourself and rerun it withstop; the report then carries that caveat.--accept-untracked-recorder -
Fallback recorders whenreports no capture source (for example Wayland without wf-recorder):
doctor/cua-driver recording start <dir>(see the cua-driver section), or the OS recorder (macOS:stop). On these paths there is no annotation overlay, so keep the annotation protocol as files — anscreencapture -v out.movlisting eachassertions.md/setup/test_startwith its result and the approximate video timestamp, exactly as in the headless path.assertion -
Never present(the synthetic pattern generator) as UI evidence. It exists to smoke-test the toolchain; the repo's
--source testexercises it.tests/test_evidence.py
以下 表示此 skill 文件夹内 的路径(无论 skill 安装在何处,例如 )。它仅需要 Python 3 和 FFmpeg。
EVIDENCEscripts/evidence.py~/.claude/skills/evidence-driven-testing/scripts/evidence.py-
首先检查:——验证
python3 $EVIDENCE doctor、ffmpeg、ffprobe和libx264filter(ass),随后检测此计算机上可用的屏幕捕获源(ready,源capture_ready会自动选择)。仅在工具链缺失时以非零状态退出;录制前请读取auto。capture_ready -
平台(会选择第一个可用项):
--source auto操作系统 源 所需条件 Linux X11 / XWayland (x11grab)x11设置 DISPLAYLinux Wayland (wf-recorder)wayland设置 ,WAYLAND_DISPLAY位于 PATH 中,并确认 compositor 支持 wlr-screencopy——可以是已知的 wlroots compositor(Sway、Hyprland、river、Wayfire、labwc、dwl、niri),也可以通过wf-recorder验证。GNOME 和 KDE Wayland 无法通过此方式捕获;wayland-info会说明这一点。对于 X11 应用,请通过 XWayland 使用doctor,或使用备用录制器。x11仍会强制选择该源--source waylandmacOS avfoundation为终端/Agent 宿主应用授予屏幕录制权限; 会列出供doctor使用的屏幕索引--screen-indexWindows gdigrab任意标准 ffmpeg 构建版本;使用 进行进程检查powershell默认捕获整个屏幕;和--geometry WxH可在 x11、wayland 和 gdigrab 上裁剪区域。XWayland 只能看到 X11 窗口,因此当被测应用原生运行于 Wayland 时,优先使用--offset X,Y源。wayland -
防崩溃的原始捕获:原始录制采用 MPEG-TS(),因此即使录制器被强制终止或崩溃,已捕获的内容仍可被探测和渲染。
raw.ts会将其重新封装或重新编码为标准stop。evidence.mp4 -
停止方式:在 Linux 上,通过 pidfd 向录制器发送信号。在 macOS 和 Windows 上,会启动一个小型 supervisor 进程,该进程拥有 ffmpeg 子进程;
start会请求它(通过会话文件夹中的stop)依次执行中断、终止、强制终止;完成后写入stop.request。绝不会向裸 PID 发送信号,因此不会误中复用后的 PID。如果录制器仍在运行时 supervisor 死亡,recorder-exit.json会拒绝执行,并告知需手动停止的 PID。如果 supervisor 在记录所启动进程之前就死亡,stop将持续阻止,直到你亲自检查是否存在游离录制器,再使用stop重新运行;报告中随后会附上该说明。--accept-untracked-recorder -
备用录制器:当报告没有可用捕获源时(例如未安装 wf-recorder 的 Wayland),可使用
doctor/cua-driver recording start <dir>(见 cua-driver 一节),或使用操作系统录制器(macOS:stop)。这些路径没有标注叠加层,因此应将标注协议保留为文件——使用screencapture -v out.mov列出每个assertions.md/setup/test_start及其结果和视频中的大致时间戳,与无头路径完全一致。assertion -
绝不将(合成图案生成器)作为 UI 证据展示。它仅用于对工具链进行冒烟测试;仓库中的
--source test会对其进行检查。tests/test_evidence.py
Instructions
指令
1. Prepare the screen
1. 准备屏幕
- Maximize the browser/app window; close popups, notifications, and extra panels.
- Navigate to the starting state (logged in, correct page) BEFORE recording, unless setup itself is under test.
- Note the exact revision under test: and
git rev-parse HEAD(or the deployment URL) — the recorder stamps them into the report.git branch --show-current
- 最大化浏览器/应用窗口;关闭弹窗、通知和多余面板。
- 在录制前导航至初始状态(已登录、正确页面),除非 setup 本身正是被测内容。
- 记录被测的准确修订版本:和
git rev-parse HEAD(或 deployment URL)——录制器会将其写入报告。git branch --show-current
2. Start recording
2. 开始录制
-
Begin the screen recording before the first meaningful action:bash
python3 $EVIDENCE start \ --output .artifacts/<task-name> \ --title "<what is being verified>" \ --commit "$(git rev-parse HEAD)" --branch "$(git branch --show-current)" \ --environment "<OS / browser / display / deployment>"It prints JSON with apath and the chosensession; keep the path (source) for every later command. The source is auto-detected and the whole screen is captured; passSESSION=...,--source,--geometry,--offset/--display(X11),--xauthority(macOS), or--screen-index(Wayland) only when--output-nameor the situation calls for it.doctor -
Add aannotation describing the starting context:
setupbashpython3 $EVIDENCE annotate "$SESSION" --type setup \ --message "Logged in, navigating to connectors page"
-
在第一个有意义的操作之前开始屏幕录制:bash
python3 $EVIDENCE start \ --output .artifacts/<task-name> \ --title "<what is being verified>" \ --commit "$(git rev-parse HEAD)" --branch "$(git branch --show-current)" \ --environment "<OS / browser / display / deployment>"它会输出 JSON,其中包含路径和选定的session;保存该路径(source)供后续每条命令使用。源会自动检测并捕获整个屏幕;仅在SESSION=...或实际情况要求时,才传入doctor、--source、--geometry、--offset/--display(X11)、--xauthority(macOS)或--screen-index(Wayland)。--output-name -
添加一条标注,描述初始上下文:
setupbashpython3 $EVIDENCE annotate "$SESSION" --type setup \ --message "Logged in, navigating to connectors page"
3. Test via computer use, annotating as you go
3. 通过 computer use 进行测试,并同步添加标注
-
Perform every interaction through computer use on the live app — the recording captures your session, so the testing and the evidence are the same act. Work at a watchable pace: let the UI settle after each action so state changes are visible on video.
-
At each named test's start, add aannotation in Jest style:
test_startbashpython3 $EVIDENCE annotate "$SESSION" --type test_start \ --message "It should execute the tool directly when permission is 'always'" -
After each check, add anannotation with
assertion,--result passed, orfailed:untestedbashpython3 $EVIDENCE annotate "$SESSION" --type assertion --result passed \ --message "Tool ran without a permission prompt" -
Rules for assertions:
- One assertion per meaningful state change — consolidate, don't annotate per UI label.
- Use "Precondition: ..." assertions to establish starting state.
- Keep under 80 characters, high-signal (the recorder rejects longer messages).
- If a test cannot run (missing prerequisite, expired auth window), mark it with the reason — never skip silently.
untested - The timestamp records when you asserted, not whether it was true — look at
the screen before choosing .
passed
-
通过 computer use 对实时应用执行每次交互——录制会捕获你的会话,因此测试与生成证据是同一行为。以便于观看的节奏操作:每次操作后等待 UI 稳定,使状态变化在视频中清晰可见。
-
每个指定测试开始时,添加一条采用 Jest 风格的标注:
test_startbashpython3 $EVIDENCE annotate "$SESSION" --type test_start \ --message "It should execute the tool directly when permission is 'always'" -
每次检查后,添加一条标注,并设置
assertion、--result passed或failed:untestedbashpython3 $EVIDENCE annotate "$SESSION" --type assertion --result passed \ --message "Tool ran without a permission prompt" -
断言规则:
- 每个有意义的状态变化对应一条断言——应合并断言,不要为每个 UI 标签分别标注。
- 使用“Precondition: ...”断言来确立初始状态。
- 保持在 80 个字符以内,并保持高信噪比(录制器会拒绝更长的消息)。
- 如果测试无法运行(缺少前置条件、授权窗口已过期),将其标记为 并说明原因——绝不能静默跳过。
untested - 时间戳记录的是你执行断言的时刻,而不是断言是否成立——选择 前先查看屏幕。
passed
4. Stop and review
4. 停止并审查
-
Stop recording after the final assertion:bash
python3 $EVIDENCE stop "$SESSION"This stops the capture (gracefully, so the recorder flushes; escalating only if it ignores the request), burns the annotations into, probes the result, and writesevidence.mp4andreport.mdnext to it. It printsmanifest.jsonon success; if rendering fails the session is marked"verified": true— fix the reported cause and runfinalization_failedagain (a retry does not signal the recorder twice). If the recorder process can no longer be signalled safely (it died, or its PID now belongs to another process), the session is markedstop. Runningrecorder_lostagain finalizes whatever video was captured, but only once that recorder process is confirmed gone — if it is still alive, stop it first, or the video would be rendered while still being written.stop -
Confirm the recording captured the key moments before sharing: extract a frame at each assertion timestamp () and check the state and the label are visible.
ffmpeg -ss <t> -i evidence.mp4 -frames:v 1 frame.png -
Fill in the Caveats section of; never leave the placeholder.
report.md
-
完成最终断言后停止录制:bash
python3 $EVIDENCE stop "$SESSION"这会停止捕获(采用优雅方式,让录制器完成数据刷新;仅当其忽略停止请求时才逐级升级),将标注烧录到,探测结果,并在其旁边写入evidence.mp4和report.md。成功时会输出manifest.json;如果渲染失败,会将会话标记为"verified": true——修复报告中的原因后再次运行finalization_failed(重试不会向录制器重复发送信号)。如果录制器进程已无法安全接收信号(进程已死亡,或其 PID 现在属于另一个进程),则会话会被标记为stop。再次运行recorder_lost会完成已捕获视频的最终处理,但前提是该录制器进程已确认消失——如果仍在运行,应先停止它,否则视频会在仍被写入时进行渲染。stop -
共享前确认录制捕获了关键时刻:在每个断言时间戳处提取一帧(),检查状态和标签是否清晰可见。
ffmpeg -ss <t> -i evidence.mp4 -frames:v 1 frame.png -
填写的 Caveats(注意事项)部分;绝不能留下占位内容。
report.md
5. Post the evidence
5. 发布证据
- is the report: what was tested, environment + exact commit, pass/fail per test, caveats. Extend it rather than rewriting from scratch.
report.md - Post the video + summary as a PR comment (embed in the PR description if
it's your PR). cannot attach a local video — upload
gh pr commentthrough the PR's comment box in an authenticated browser, or upload it to a host and link it (for example theevidence.mp4upload adapters). Reopen the comment and confirm the video plays before claiming it is posted.before-and-after - Attach the same video to the tracker issue (Linear/Jira) with a one-line result.
- Send the report + recording to the requester.
- 是报告:记录测试内容、环境和准确 commit、各项测试的通过/失败情况以及注意事项。应在现有内容上补充,不要从头重写。
report.md - 将视频和摘要发布为 PR 评论(如果是你的 PR,则嵌入 PR 描述中)。无法附加本地视频——请通过已登录的浏览器在 PR 评论框中上传
gh pr comment,或上传到托管服务并提供链接(例如evidence.mp4上传适配器)。重新打开评论并确认视频可以播放后,才能声称已发布。before-and-after - 将同一个视频附加到跟踪 issue(Linear/Jira),并附上一行结果。
- 将报告和录屏发送给请求方。
Guardrails
防护规则
- The video must show the actual test session being driven live. Never present
scripted playback, stitched clips, or synthetic footage as a recording; if
the harness lacks computer-use tools but a GUI exists, drive via
; with no GUI at all, use the headless path instead.
cua-driver - Never record a half-covered or tiled window — maximize first.
- Never record a screen showing secrets, tokens, customer data, or payment
details; if a flow requires them, mark it and say why.
untested - When verifying a fix, show or reference the old failure alongside the new success.
- Always state the exact commit/branch/deployment tested against.
- 视频必须展示实际执行的实时测试会话。绝不能将脚本回放、拼接片段或合成画面作为录制内容展示;如果测试框架缺少 computer use 工具但存在 GUI,请通过 驱动;如果完全没有 GUI,请改用无头路径。
cua-driver - 绝不能录制被其他窗口遮挡一半或以分块平铺显示的窗口——应先最大化窗口。
- 绝不能录制显示密钥、token、客户数据或支付信息的屏幕;如果某个流程必须使用这些信息,则将其标记为 并说明原因。
untested - 验证修复时,应展示或引用旧故障以及修复后的成功结果。
- 始终说明被测的准确 commit/branch/deployment。
No computer-use tools? Drive with cua-driver (GUI available)
没有 computer use 工具?使用 cua-driver 驱动(有 GUI)
When a display exists but the agent has no built-in computer-use capability,
use cua-driver (macOS / Windows / Linux) as
the actuator. It is still you testing the app live — the recording rule holds
unchanged; only the input mechanism differs.
- Verify the setup with before recording. If a
cua-driver doctorskill is installed, read it and follow its protocol — the snapshot-before-action invariant is mandatory.cua-driver - Loop per interaction: →
launch_app(accessibility treeget_window_state- screenshot) → act via (
element_token,click,type_text) →press_keyfor the expected postcondition. Eachverify_statecheck maps 1:1 onto anverify_stateannotation.assertion
- screenshot) → act via
- Wherever reports
doctor, keep using the bundled recorder above for the video and the annotations; cua-driver only supplies the input.capture_ready: yes - Otherwise, /
cua-driver recording start <output-dir>is the recorder (the output directory is required, and the daemon must be running:cua-driver recording stop). Video capture is on by default and is finalized tocua-driver serveon stop — but on Windows/Linux it shells out to ffmpeg, so a missing ffmpeg or display yields only the per-turn trajectory folders (before/after screenshots,<output-dir>/recording.mp4,action.json), no video. After stopping, verifyclick.pngexists before citing it; if it is absent, fix the recorder or present the per-turn before/after screenshots as numbered captures per the headless protocol.recording.mp4 - If no annotation overlay is available on this path, keep the protocol as
files: an listing each
assertions.md/test_startwith its result, exactly as in the headless path.assertion
当存在显示器但 Agent 没有内置 computer use 能力时,使用 cua-driver(macOS / Windows / Linux)作为执行器。这仍然是你实时测试应用——录制规则保持不变;唯一的区别是输入机制不同。
- 录制前使用 验证配置。如果已安装
cua-driver doctorskill,请阅读并遵循其协议——“操作前先截屏”原则是强制要求。cua-driver - 每次交互按以下流程循环:→
launch_app(可访问性树 + 截图)→ 通过get_window_state执行操作(element_token、click、type_text)→ 使用press_key验证预期后置状态。每次verify_state检查都与一条verify_state标注一一对应。assertion - 无论 在何处报告
doctor,都应继续使用上述内置录制器来生成视频和标注;cua-driver 仅负责提供输入。capture_ready: yes - 否则,使用 /
cua-driver recording start <output-dir>作为录制器(必须提供输出目录,并且守护进程必须正在运行:cua-driver recording stop)。默认启用视频捕获,停止后最终生成cua-driver serve——但在 Windows/Linux 上,它会调用 ffmpeg,因此如果缺少 ffmpeg 或显示器,只会生成每轮操作的轨迹文件夹(操作前后截图、<output-dir>/recording.mp4、action.json),而不会生成视频。停止后,引用视频前先确认click.png存在;如果不存在,应修复录制器,或按照无头路径协议,将每轮操作前后的截图作为带编号的捕获结果展示。recording.mp4 - 如果此路径没有可用的标注叠加层,应将协议保留为文件:使用 列出每个
assertions.md/test_start及其结果,与无头路径完全一致。assertion
Headless path (no GUI available)
无头路径(没有 GUI)
When the agent has no desktop to record, keep the same assertion discipline;
swap the recorder for scripted capture:
-
Save everything to(gitignore it — evidence gets uploaded, never committed). Keep the capture script beside the captures so the run is repeatable.
.artifacts/<task-name>/ -
Screenshots: theCLI (
before-and-after) captures URLs or elements and its pairs feed PR embeds directly. In containers/VMs where Chrome fails with "No usable sandbox", set@vercel/before-and-after.AGENT_BROWSER_ARGS="--no-sandbox" -
Video / multi-step flows: a one-off Playwright script, run without adding playwright to the project's dependencies:bash
npx --yes --package=playwright node record.mjs(Plainfails —npx playwright node record.mjsis not a Playwright CLI command;nodeis what puts the module on the path.) Minimal--package=playwright:record.mjsjsimport { chromium } from "playwright"; const browser = await chromium.launch(); const context = await browser.newContext({ recordVideo: { dir: ".artifacts/<task-name>/" }, }); const page = await context.newPage(); await page.goto("http://localhost:3000/path-under-test"); // ...drive the flow, one meaningful state change per step... await context.close(); // finalizes the .webm await browser.close();Trim or compress with ffmpeg if the file is large. -
The annotation protocol becomes files: number captures in test order with the assertion in the name —,
01-precondition-signed-in.png— and keep an02-it-saves-on-blur-passed.pngin the artifacts folder listing eachassertions.md/test_startwith its result (assertion/passed/failed+ reason).untested
当 Agent 没有可录制的桌面时,保持相同的断言规范;将录制器替换为脚本化捕获:
-
将所有内容保存到(将其加入 gitignore——证据会上传,绝不提交到仓库)。将捕获脚本保存在捕获结果旁边,以确保运行过程可重复。
.artifacts/<task-name>/ -
截图:CLI(
before-and-after)可捕获 URL 或元素,其成对结果可直接用于 PR 嵌入。在 Chrome 因@vercel/before-and-after而无法运行的容器/VM 中,设置"No usable sandbox"。AGENT_BROWSER_ARGS="--no-sandbox" -
视频 / 多步骤流程:编写一次性 Playwright 脚本,运行时无需将 playwright 添加到项目依赖中:bash
npx --yes --package=playwright node record.mjs(普通的会失败——npx playwright node record.mjs不是 Playwright CLI 命令;node才会将模块加入可执行路径。) 最小化--package=playwright:record.mjsjsimport { chromium } from "playwright"; const browser = await chromium.launch(); const context = await browser.newContext({ recordVideo: { dir: ".artifacts/<task-name>/" }, }); const page = await context.newPage(); await page.goto("http://localhost:3000/path-under-test"); // ...drive the flow, one meaningful state change per step... await context.close(); // finalizes the .webm await browser.close();如果文件较大,可使用 ffmpeg 裁剪或压缩。 -
标注协议改为文件:按照测试顺序为捕获结果编号,并在文件名中加入断言——例如、
01-precondition-signed-in.png——同时在 artifacts 文件夹中保留02-it-saves-on-blur-passed.png,列出每个assertions.md/test_start及其结果(assertion/passed/failed+ 原因)。untested
Non-UI changes still need evidence
非 UI 变更同样需要证据
- API / performance: a scripted probe with measured numbers — request
counts per phase, latency before/after — captured to .
probe-output.txt - Rendering / canvas / shader: rendered frames plus pixel assertions (diff values), reviewed by eye and saved as PNGs.
- Agent behavior: the relevant transcript excerpt showing the tool call and response.
- Bug fixes: reproduce and capture the failure before writing the fix — that capture is the "before" half of a before/after pair.
- API / 性能:运行脚本化探针并记录测量数值——各阶段的请求数、前后延迟等——输出到 。
probe-output.txt - 渲染 / canvas / shader:保存渲染后的帧以及像素断言(diff 数值),由人工审查并保存为 PNG。
- Agent 行为:提供相关对话记录摘录,其中包含工具调用及其响应。
- Bug 修复:在编写修复前复现并捕获故障——该捕获结果就是前后对比中的“修复前”部分。
Capture hygiene
捕获规范
- Confirm the server you're probing is running your code (right port,
right process), especially when multiple agents share a machine:
— or where
lsof -i :<port>isn't installed,lsofto find the listener's PID, thenss -ltnp "sport = :<port>"to confirm it's yours.ps -p <pid> -o args= - Evidence complements the repo's checks (typecheck/build/tests); it never replaces them.
- Hand before/after media pairs to a before/after tool for the PR embed
(e.g. ).
before-and-after before.png after.png --markdown
- 尤其是在多个 Agent 共享同一台机器时,确认所探测的服务器运行的是你的代码(端口正确、进程正确):使用 ;如果未安装
lsof -i :<port>,则使用lsof查找监听进程的 PID,再通过ss -ltnp "sport = :<port>"确认该进程属于你。ps -p <pid> -o args= - 证据是对仓库检查(typecheck/build/tests)的补充;绝不能替代这些检查。
- 将前后媒体对交给 before/after 工具,以生成 PR 嵌入内容(例如 )。
before-and-after before.png after.png --markdown