惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
SegmentFault 最新的问题
月光博客
月光博客
大猫的无限游戏
大猫的无限游戏
GbyAI
GbyAI
博客园 - 叶小钗
小众软件
小众软件
WordPress大学
WordPress大学
I
InfoQ
Last Week in AI
Last Week in AI
Vercel News
Vercel News
博客园 - Franky
Stack Overflow Blog
Stack Overflow Blog
P
Proofpoint News Feed
A
About on SuperTechFans
Engineering at Meta
Engineering at Meta
腾讯CDC
D
DataBreaches.Net
有赞技术团队
有赞技术团队
宝玉的分享
宝玉的分享
Jina AI
Jina AI
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
G
Google Developers Blog
V
Visual Studio Blog
酷 壳 – CoolShell
酷 壳 – CoolShell

暗无天日

读:AI Agent 安全日志——从可见性与隐私的两难说起 - 暗无天日 读:AI Agent 生产化——一份从原型到上线的速查清单 - 暗无天日 AI写作的语言指纹——如何让文字不那么像机器 - 暗无天日 读:50 条 Claude Code 技巧——一个工程经理的六个月使用心得 读:AI 辅助开发为什么让 E2E 测试更有价值 - 暗无天日 读:在Emacs中使用Claude Code(Spacemacs适配版) - 暗无天日 Claude Code 背后的工程哲学——读 Agent Harness Engineering 读:Agent Harness Engineering——AI 智能体不只是模型,还有套件 - 暗无天日 browser-harness:让 AI 直接接管你的浏览器 - 暗无天日 读:Security-First CI/CD —— DevSecOps 自动化实践指南 TIL: 数字小键盘的小数点陷阱与行内算术求值 - 暗无天日 读:Immutability 不是万能药,它是一种权衡 - 暗无天日 Conducty:给 Claude Code 加上项目记忆和并行执行能力 - 暗无天日 读 — GitHub Trending 里的 Claude Code 技能包 读 — Prompt Caching 省钱指南 TIL: Emacs 中那些跟鼠标配合的冷门快捷键 - 暗无天日 读:Anvil——把 Emacs 变成 AI 的工具服务器 读:Emacs 代码折叠终极指南 - 暗无天日 读:Clojure 搭车客指南 - 暗无天日 git推送失败后恢复仓库损坏的完整记录 - 暗无天日 多智能体系统的两个有效模式——以及对 Claude Code 用户的启示 - 暗无天日 用 Org Babel 写 Literate 博文:扩展执行 + 定制导出 proced:Emacs 内置的进程查看器 - 暗无天日 从 proced 定制中学到的 Elisp 模式 读:让 Emacs proced 在 macOS 上显示 CPU 和内存 异步编程的函数着色税 - 暗无天日 链式调用的代价:JavaScript 和 Clojure 的共同教训 - 暗无天日 hyperfine:命令行基准测试工具 - 暗无天日 管道中的变量去哪了?——子 shell 作用域陷阱 - 暗无天日 开源包装器的信任陷阱:四个危险信号 - 暗无天日
读:llm-test —— 用 LLM agent 驱动 Emacs 测试
2026-04-23 · via 暗无天日

Andrew Hyatt(Emacs 核心贡献者)最近开源了一个实验性项目1llm-test 。它的核心想法是——用 LLM 代替人来测试 Emacs 包。你用自然语言描述"用户应该看到什么",LLM agent 会启动一个干净的 Emacs 进程,像人一样操作它(按键、输入文字、执行命令),然后判断测试是否通过。

怎么工作

整个流程分四步:

  1. 用 YAML 文件写测试描述,就是一段英文说明要测什么、期望什么结果
  2. llm-test 解析 YAML,为每个测试描述注册一个 ERT 测试
  3. 运行测试时,启动一个 emacs -Q 的干净 daemon 进程
  4. LLM agent 通过 tool calling 驱动这个 Emacs,直到判定通过或失败
group: auto-fill mode
setup: |
  Enable auto-fill-mode in a text-mode buffer.
  Set fill-column to 40.
tests:
  - description: |
      Type a long paragraph that exceeds fill-column.
      Verify that the text is automatically wrapped.
  - description: |
      Type a numbered list item that exceeds fill-column.
      Verify that continuation lines are indented properly.

这个例子测试的是 auto-fill-mode :开一个文本 buffer,设置 fill-column 为 40,然后让 LLM 输入一段超过 40 列的文字,检查 Emacs 是否自动换行了。测试描述就是自然语言,不需要写一行 Elisp。

Agent 怎么"看" Emacs

LLM agent 看不到图形界面——测试 Emacs 是以 daemon 模式运行的。那它怎么知道 Emacs 当前什么状态?

答案是:每次 agent 执行完一个操作(按键、执行命令、eval 代码等), llm-test 会自动附加一份 JSON 格式的 frame 快照。这个快照包含当前所有窗口的可见内容(就像截图,但是文字版)、光标位置、minibuffer 状态和 echo area 消息。

{
  "selected-window": {"number": 0, "buffer": "<buffer name>"},
  "windows": [
    {
      "number": 0,
      "buffer": "<buffer name>",
      "mode": "<major mode>",
      "point": 1,
      "lines": ["<visual line 1>", "<visual line 2>"]
    }
  ],
  "minibuffer": {"active": false, "prompt": "", "input": ""},
  "message": "<echo area message>"
}

Agent 不需要主动请求"给我看看现在屏幕上有什么"——每次操作后自动收到。这让 agent 的行为更像真人:按了一个键,"看"到结果,决定下一步做什么。

Agent 可以调用的工具包括:

  • eval-elisp :在测试进程中执行任意 Elisp 并返回结果
  • send-keys :模拟按键(如 C-x C-fM-x
  • type-text :逐字输入文本(保留空格和特殊字符)
  • run-command :按名称执行命令(比 M-x 更可靠)
  • sleep :等待异步操作完成
  • suggest-improvement :记录 UI/UX 改进建议(不影响测试结果)
  • pass-test / fail-test :判定测试结果,结束循环

整个 agent loop 最多跑 80 轮( llm-test-max-iterations 默认值),每轮是一次 LLM 请求/响应往返。

跟传统测试的区别

传统的 Emacs 测试用 ERT(Emacs Lisp 测试框架),测试代码直接调用函数、检查返回值。比如测试 auto-fill ,你要写 Elisp 设置 buffer、插入文字、检查换行位置。这测的是 函数的行为

llm-test 测的是 用户的体验 。Agent 不知道你的内部函数怎么调用——它只知道按键、看屏幕、判断结果是否符合描述。这跟真实用户使用 Emacs 的方式一模一样。

这种思路的优势:

  • 能测传统测试很难覆盖的场景 :比如" M-x 输入命令时的补全是否正确"、" dired 中按 g 刷新后文件列表是否更新"——这些涉及多个命令组合和 UI 状态变化的交互流程,用 Elisp 写测试非常痛苦,用自然语言描述却很自然
  • 测试描述就是文档 :YAML 里的自然语言描述既是测试用例,也是用户行为的文档
  • 对被测代码零侵入 :不需要为测试暴露内部接口或写 test helper

但也有明显的代价:

  • 非确定性 :同一个测试跑两次,LLM 可能走不同的操作路径,甚至得出不同的结论。这不是传统测试的"确定性"范式
  • 成本 :每个测试都要多次调用 LLM API,一个测试组跑下来可能消耗不少 token
  • 速度 :每轮 agent loop 都是一次 API 调用,比直接 eval Elisp 慢几个数量级
  • 依赖模型质量 :Andrew Hyatt 在 README 中建议使用 Claude Sonnet 级别的模型,不过他指出只要指令足够清晰,便宜的模型也能胜任

"LLM 当测试员"的适用场景

llm-test 不会取代传统 ERT 测试。对于"函数 f(x) 输入 5 应该返回 10"这类确定性逻辑测试,Elisp 单元测试更快更准。

它适合的是另一类测试——那些"人一眼就能看出来对不对,但用代码描述很麻烦"的场景:

  • 包的 UI 工作流是否顺畅(按键 → 期望看到某个界面)
  • 多步骤交互的端到端验证(打开文件 → 编辑 → 保存 → 确认状态)
  • 发现 UI/UX 问题( suggest-improvement 工具让 agent 可以主动提出改进建议)

这个思路也可以延伸到其他 GUI 应用——只要你能给 LLM 提供"屏幕状态"和"操作接口",就能用同样的 agent loop 模式做测试。 llm-test 的 frame state JSON 快照设计就是一个很好的参考:不需要真的截图,把视觉信息结构化为文本就够了。