纯自然语言编写 E2E 测试。 以 $0 回放它们。

LLM 只规划一次浏览器操作。从第二次运行起,Windup 进行确定性回放零 LLM 调用 —— ~1 秒、$0,结果稳定。你编辑的是测试场景,而非选择器。

$ npm i -D windupjs
  • 无需选择器,无需测试代码
  • 回放时 llm_calls=0
  • 底层由 Playwright 驱动
windup run checkout
终端录制:运行一个自然语言场景;首次运行进行规划,llm_calls=1,第二次运行从缓存回放,llm_calls=0、$0
真实终端 —— 首次运行进行规划(llm_calls=1),第二次运行从缓存回放,成本 $0

问题所在

手写的 E2E 测试,每当选择器变动就会失效。在每次运行时都驱动浏览器的 AI 智能体则速度慢、不确定,且每个测试都要向你收取一次 LLM 调用的费用。

Windup 只规划一次,并缓存一份经过验证的操作计划。回放是确定性的,且免费。当应用发生变化、某个检查失败时,计划会失效并自动重新规划 —— 自愈,而不是悄无声息地出错。

工作原理

用 LLM 规划一次,然后无需它进行回放。

最昂贵的部分 —— 弄清楚该执行哪些浏览器操作 —— 只发生一次,并被转化为缓存的、可验证的数据。

  1. 1

    规划(一次)

    一个自然语言任务交给规划器。LLM 产出一份 JSON 操作计划 —— 一次调用,仅在首次运行时发生。

    llm_calls=1 · ~$0.0025
  2. 2

    执行 + 验证

    一个确定性执行器(Playwright)运行该计划。廉价的 DOM/URL 后置条件验证每个操作 —— 无需 LLM。

    可信输入事件
  3. 3

    回放(免费)

    轨迹被缓存下来。之后每次运行都回放它:零 LLM 调用、~1 秒、$0,每次都是同一份计划。

    llm_calls=0 · $0
  • 计划是数据,而非代码 — 经过 schema 校验的 JSON —— 没有运行时即兴发挥。
  • 无需 LLM 的验证 — 后置条件在每个操作上检查 DOM/URL。
  • 自愈缓存 — 检查失败会使计划失效 → 重新规划。
  • 零硬编码的站点知识 — 引擎事先对你的应用一无所知。

为什么选 Windup

脚本的可靠性,自然语言的顺手。

手写脚本运行成本低,但维护成本高。每次运行都调用 AI 的智能体易于编写,但速度慢且不确定。Windup 各取二者之长。

维度 手写脚本 每次运行都用 AI 智能体 Windup
编写方式 代码 + 选择器 自然语言 自然语言
每次运行成本 $0 每次运行都调用 LLM 仅首次运行调用 LLM
速度 慢(模型在回路中) ~1s 回放
确定性 低(每次即兴发挥) 高(每次都是同一份计划)
应用发生变化 你去修脚本 可能悄无声息地做错事 检查失败 → 重新规划

功能特性

QA 工作流所需的一切 —— 唯独不要选择器。

一款为真实项目打造的 CLI:场景编写、密钥管理、依赖关系、成本追踪和 CI 报告器。

自然语言场景

用纯自然语言描述测试。无需选择器、无需页面对象、无需维护测试代码。

规划一次,免费回放

从第二次运行起:llm_calls=0、~1s、$0。缓存的计划每次都以相同方式运行。

确定性执行

Playwright 配合可信输入事件(isTrusted)—— 可靠的点击、输入与导航。

廉价验证

每个操作都检查 DOM/URL 后置条件,回路中没有 LLM。

windup new

LLM 辅助编写:根据你应用的真实页面(站点地图)+ 项目清单生成场景。--validate 会运行并不断改进,直到通过。

windup scan

直接从源代码(Next.js、react-router)索引你的路由和元素。

windup secret

凭据从不进入场景、缓存、LLM 提示词或 git —— 只有 ENV:* 引用,在运行时解析。

depends_on

场景之间的依赖关系(例如「创建发票」依赖「登录」)—— 同一会话,按依赖分别缓存。

run --summary

AI 撰写一份运行后的复盘,引用真实观察到的值 —— 价格、消息、确认信息。

run --suggest

失败时,AI 阅读真实页面并对你的场景提出修复建议。

CI 报告器

JUnit、JSON 和自包含的 HTML(--reporter)。任何失败都会返回非零退出码。

多提供商

Google Gemini 和 OpenAI,可按次运行选择(--llm openai:gpt-5-mini)。windup costs 按提供商和模型追踪花费。

run --concurrency

在一个共享的热浏览器上以隔离的上下文并行运行多个场景 —— 混合套件下约快 2 倍,在有规划或长流程时更快。默认串行。

跨浏览器

用 --browser 在 Chromium(默认)、Firefox 或 WebKit 上运行相同的场景。同一份计划可在三者上回放 —— 编写一次,处处运行。

示例

一个场景就是 JSON 里的自然语言。两次运行讲清全部故事。

你只写意图。首次运行进行规划并支付几分之一美分;此后每次运行都是缓存回放,成本 $0

checkout.json 场景
{
  "scenario_id": "checkout",
  "task": "Log in as the qa account, add 'Backpack' to the cart, check out and verify the order confirmation message appears."
}
windup run checkout 输出
$ windup run checkout      # 1st run
PASS  checkout  cache=miss llm_calls=1 total=3003ms cost=$0.0024

$ windup run checkout      # again — deterministic replay
PASS  checkout  cache=hit  llm_calls=0 total=671ms  cost=$0

cache=hit · llm_calls=0 · $0 —— 第二次运行从不触及模型。

CI / CD

把它放进你的流水线。退出码和报告一应俱全。

在一个热浏览器中运行整个套件,任何场景失败都让构建失败,并产出机器可读或人类可读的报告。

ci —— 一行搞定 bash
$ npx windup run --all --reporter junit \
    --report-file reports/windup.xml
  • --all 在一个热浏览器中为整个套件运行每个场景。
  • --concurrency <n> 并行运行场景(混合套件下约快 2 倍);--browser firefox|webkit 进行跨浏览器运行。
  • 任何场景失败时返回非零退出码。
  • --reporter junit|json|htmlwindup costs --json 追踪流水线中的 AI 花费。

可靠性

确定性,就是货真价实的确定性。

回放是实测出来的,不是承诺出来的。缓存的计划每次运行都产出相同结果 —— 没有模型,没有抖动。

60/60
缓存回放通过
4 个场景 × 15 次回放 —— 零抖动
llm_calls=0
每次回放
登录 · 多步结账 · 添加/移除 · 第 2 个站点
~$0.0025
每次生成
默认模型,gemini-3.1-flash-lite
106 routes
生产环境自用
在真实生产应用上运行
Windup 吉祥物举着一个绿色对勾

快速开始

五条命令,从零到一个可回放的测试。

Node ≥ 20,以及一个 API 密钥 —— GOOGLE_GENERATIVE_AI_API_KEY(Google,默认)或 OPENAI_API_KEY(OpenAI)—— 放在 .env.local 中。密钥仅用于规划;缓存回放从不调用 LLM。

Windup 吉祥物在奔跑
$ npm i -D windupjs
Chromium 会自动配置
$ npx windup init
3 个问题 → windup.config.ts
$ npx windup scan
从源代码索引你应用的路由
$ npx windup new "log in and create an invoice for ACME"
LLM 辅助编写
$ npx windup run checkout
首次运行规划 · 此后回放 ~1s、$0
Node ≥ 20Google Gemini OpenAIPlaywright 已内置MIT

面向 AI 时代

让你的 AI 来搭建测试。

如今没人再读文档了 —— 大家都把它交给助手。所以 Windup 附带了一份 llms.txt:整套文档,为机器结构化组织。把你的编码智能体指向它,用纯自然语言描述流程,它就会为你编写并运行场景。

1

把文档交给你的 AI

将此 URL 粘贴到你的助手(Claude、Cursor、Copilot……)中。

https://windup.run/zh/llms.txt
2

描述要测试什么

一段现成可粘贴的起始提示词 —— 填入你的流程即可。

阅读 https://windup.run/zh/llms.txt 并为我的应用搭建 Windup E2E 测试,然后为以下流程编写场景:……