入门
简介
danwo 是一个面向 Web 和移动应用的端到端测试框架。先测试 UI,需要时再加上后端。
danwo 是一个开源的 Web 与移动应用端到端测试框架。测试会打开你的应用,像用户一样点击和输入,并检查屏幕上显示的内容。它可以在浏览器、Android 和 iOS 上运行。
import { test } from "@danwo/sdk"
test("signs up", async ({ app, screen, expect }) => {
await app.open("/sign-up")
await screen.getByLabel("Email").fill("[email protected]")
await screen.getByLabel("Password").fill("correct horse battery staple")
await screen.getByRole("button", { name: "Create account" }).click()
await expect(screen.getByRole("heading", { name: "Welcome, Ada" })).toBeVisible()
})这就是一个完整的测试。danwo 会启动你的应用,打开一个全新的浏览器,并在每次点击后等待页面稳定,所以不需要写 sleep。它不需要第三方服务、不需要 API 密钥,也不需要模型。
概览
| 你想要 | danwo |
|---|---|
| 测试 Web 应用 | Chromium、Firefox 和 WebKit,同一个测试可在多个浏览器中运行。参见 Web。 |
| 测试移动应用 | Android 模拟器和 iOS 模拟器:Expo、Flutter、SwiftUI 或 UIKit、Jetpack Compose 或 View。参见 Android。 |
| 让 AI 编程助手来测试 | 为 Claude Code、Cursor、Codex 和 Copilot 提供的 Skill 和 MCP 服务器。参见 AI 编程助手。 |
| 保留或迁移现有测试 | 把 danwo 加入 Playwright Test,或从 Cypress 或 Detox 一次迁移一个文件。 |
| 在 CI 中运行 | 每个 pull request 都有一个 Check 和一条评论,另有适用于任何 CI 的 分片 和 JUnit 报告。参见 CI。 |
| 检查界面背后发生了什么 | 模拟的第三方服务、不变性校验(invariant)和故障矩阵:见下面的几层。 |
按需添加各层
第一个测试之后的一切都是可选的。每一层都建立在前一层之上,你可以在任何一层停下。
1. 定位器测试
定位器按用户称呼元素的方式查找元素:一个叫“Pay”的按钮,一个标签为“Email”的输入框。定位器从不调用模型。参见智能体与定位器。
await screen.getByRole("searchbox", { name: "Search" }).fill("blue mug")
await screen.getByRole("link", { name: "Blue mug" }).click()
await expect(screen.getByText("In stock")).toBeVisible()2. 用自然语言编写的智能体步骤
当某一步说起来比精确定位更容易时,就用自然语言写。第一次运行需要一个模型和它的 API 密钥:由智能体想出如何完成这一步,danwo 把它录制下来。之后的运行直接回放录制,不再调用模型。这同样适用于 assert、waitFor 和 extract,而不只是操作。参见智能体步骤。
await agent.act("add two blue mugs to the basket and go to checkout")
await agent.assert("the basket shows two blue mugs")
await agent.waitFor("the delivery options have loaded")3. 截图与视觉对比
toHaveScreenshot 把整个页面或某个元素与保存在测试旁边的基线图片进行对比。每次运行都会变化的内容(比如时钟)可以遮盖掉。参见视觉对比。
await expect(screen).toHaveScreenshot("home", { mask: [screen.getByTestId("clock")] })第 1 到第 3 层本身就是一套完整的端到端配置:注册、登录、搜索、表单和结账页面,覆盖 Web 和移动端,并提供视频和仪表盘。测试范围列出了常见的用户流程,以及每种流程所需的层。
当问题藏在界面背后
屏幕上可能显示“Thank you”,而 Stripe 却对这张卡扣了两次款,或者收据邮件根本没有发出。接下来的三层检查一次点击在页面背后做了什么。
4. 模拟的第三方服务
danwo 会把你的应用启动在一个出站代理(egress proxy)后面,所有发出的请求都要经过这个代理。它用本地模拟器应答 Stripe、Clerk、Resend 以及另外大约二十个服务。不需要沙箱密钥,也不需要改代码。参见模拟器。
environment: () => appEnvironment({ app, services: [stripeService(), resendService()] }),5. 不变性校验
不变性校验是一条无论测试过程如何都必须成立的规则。它读取你的数据库和模拟器,并检查两者是否一致。参见编写不变性校验。
}).invariant(async ({ databaseUrl, resend, expect }) => {
expect(await sql(databaseUrl, "select id from signups where email = $1", [EMAIL])).toHaveLength(1)
expect(resendInbox(resend).list(EMAIL)).toHaveLength(1)
})6. 故障矩阵
故障矩阵是 danwo 内置的故障注入功能。它针对每一种可能出错的情况把测试重放一次:卡被拒付、一个 500 错误、重复的 webhook、被双击的按钮。由不变性校验来判定每一次运行的结果。
npx @danwo/cli matrix tests/waitlist.danwo.ts后端层如何协同工作
无论使用到哪一层,每次运行都会留下一份完整的运行记录(就像飞机的黑匣子):屏幕录像、每一步操作,以及在启用后端层时的每一次调用、每个 webhook 和每条数据库语句。参见运行记录。
AI 编程助手也能使用它
danwo init 会询问你使用哪些 AI 编程助手,并为每个助手配置 danwo 的 Skill 和 MCP 服务器。Skill 教它如何编写 danwo 测试,MCP 服务器让它可以运行测试、操作你的应用并读取运行记录。这样,修改你代码的 AI 编程助手就能通过 UI 检查自己的工作,并修复失败的地方。参见 AI 编程助手。
Coding agents
created .claude/skills/danwo/SKILL.md
created .agents/skills/danwo/SKILL.md
created .mcp.json
created .cursor/mcp.json
created .codex/config.toml