Control CLI
使用可重复的本地装置来演练交互式 CLI,而不是手动反复试探。优先复用仓库自带的测试/演示装置;若不存在,则用标准本地工具临时搭建一套装置。
用途
用确定性输入复现 CLI/TUI 缺陷;验证键盘流程、提示、中断、缩放行为与终端布局;为缺陷修复捕获修复前后的转录;剖析启动时间、慢操作、卡死或内存增长;当输出比解释更直观时录制简短终端演示。
装置循环
- 确定被测命令与最小可复现工作区。
- 发现已有的本地装置:package scripts、e2e 测试、演示录制器、expect 脚本或 PTY 辅助工具。
- 若无装置,在隔离的终端会话中以确定性环境变量启动 CLI。
- 交互前捕获当前屏幕。
- 每次只发送一个动作:文本、Enter、方向键、Escape、Ctrl-C、缩放。
- 等待出现明确的屏幕模式或提示后再进行下一个动作。
- 保存转录与剖析产物。
- 干净地结束会话。
装置选项
- 仓库原生装置:优先使用已入库的脚本,因为它们了解应用的启动、环境与提示。
- tmux:受管会话、capture-pane、send-keys、attach/detach。
- PTY 探针:当 tmux 不可用时,使用简短的 Python、Node 或 Expect 脚本。
- 运行时检查器:使用 Node 或 Bun inspector 获取 CPU 剖析、堆快照与实时求值。
- 终端录制器:当用户要求演示时,使用仓库本地演示工具或兼容 asciinema 的工具。
最小 tmux 装置
SESSION="cli-harness-$(date +%s)" tmux new-session -d -s "$SESSION" -- <command-under-test> tmux capture-pane -pt "$SESSION" tmux send-keys -t "$SESSION" "help" Enter tmux capture-pane -pt "$SESSION" tmux kill-session -t "$SESSION"
对于 Node CLI:
NODE_OPTIONS="--inspect=127.0.0.1:0" tmux new-session -d -s "$SESSION" -- <node-cli-command>
读取终端输出以找到 inspector URL,若需剖析再使用兼容 Chrome DevTools 的工具。
最小 PTY 装置
当仓库没有 tmux 或演示装置却需要确定性等待时,使用 PTY 脚本。除非用户要求加入可复用测试,否则保持其为临时脚本。
import os import pty import select import subprocess import time
master_fd, slave_fd = pty.openpty() proc = subprocess.Popen( ["<command>", "<arg>"], stdin=slave_fd, stdout=slave_fd, stderr=slave_fd, close_fds=True, ) os.close(slave_fd)
deadline = time.time() + 30 buffer = b"" while time.time() < deadline: ready, _, _ = select.select([master_fd], [], [], 0.25) if not ready: continue chunk = os.read(master_fd, 4096) buffer += chunk if b"<ready text>" in buffer: os.write(master_fd, b"help\n") break
print(buffer.decode(errors="replace")) proc.terminate() os.close(master_fd)
若 CLI 需要更丰富的终端控制,使用 pty.fork() 或已有的 PTY 库。
剖析配方
- 启动回归:在相同的机器、环境与命令下捕获基线与处理后的启动耗时。
- 慢操作:启动 CPU 剖析,执行操作,停止剖析,比较顶部自耗时函数。
- 内存泄漏:若可用则强制 GC,取堆快照,重复执行操作,再次强制 GC,再取一次快照。
- 卡死:在中断前捕获屏幕、活动句柄/资源以及栈/CPU 采样。
护栏
- 优先使用确定性等待而非 sleep。若必须 sleep,需说明原因。
- 不要向受控会话发送凭据或破坏性命令。
- 除非仓库已有测试/演示装置,否则将装置放在 /tmp。
- 不要硬编码来自其他仓库的路径。根据当前仓库的脚本与运行时调整命令。
- 清理 tmux 会话、临时目录、inspector 进程与演示产物,除非用户要求保留。