TestTrout
TestTrout
面向 AI 构建应用的测试助手。
你可以把它当作一个应用来运行,也可以通过 MCP 交给你的编码代理。无论哪种方式,它都会为你写出应用从未有过的测试,并在测试失败时及时告知你。
鳟鱼是指示物种。它们只生活在清澈、含氧量高的水中——如果你在溪流中发现一条鳟鱼,不用亲自检测就知道水质是健康的。
一套好的测试套件正是如此:它不是一件苦差事,而是一个一眼就能读懂的信号。
问题所在
编码代理交付速度很快,但也会悄无声息地破坏东西,而且它们构建的应用——Lovable、v0、Bolt,以及在 Vercel 上手工搭建的 React 应用——几乎从来都没有测试。于是整个循环以写出代码的那个家伙的一句"看起来没问题"告终。
TestTrout 补上了这个闭环。它读取代码仓库,连接正在运行的部署,找出哪些功能未被测试以及按什么顺序测试最重要,编写真正的测试,运行它们,并报告你可以真正据此行动的结果。
Related MCP server: Lastest
让它跑起来
pip install testtrout
trout up存储、一个 worker,以及位于 localhost:7411 的界面。无需 Docker、无需守护进程、无需安装数据库——SQLite 位于 ~/.testtrout 下,worker 在进程内运行。不需要任何 API 密钥。 这里没有任何东西调用模型。
工作原理
添加一个项目——本机上的一个文件夹,以及它部署所在的 URL。
trout add ~/code/my-app --url https://my-app.vercel.app然后是四个步骤,也就是四条命令:
trout look # read the code, ask the deployment, work out what is testable
trout facts # what I still need from you — all optional
trout build # write the baseline and prove it
trout run # re-run it and report what changed基线就是你的部署当前的行为。 TestTrout 记录下这些行为,并断言它们持续保持。它并不知道当前行为是否正确——没有人告诉过它——它也永远不会问。它只知道行为是什么,并在行为发生变化的那一天察觉出来。
正是这一条规则,决定了为什么没有访谈、没有审批队列、也没有关于你产品的一系列问题。它唯一会问的,是它无法自行发现的那些具体值:
它要求提供 | 原因 |
部署 URL | 仅凭代码无法测试任何东西 |
API URL | 仅当你的后端部署在独立主机上时 |
一个账号 | 仅当某个请求确实拒绝了未认证的访问时 |
一个真实 ID | 仅当探针无法自行访问 |
每一项都能在几秒内回答,每一项都是可选的,而且每一项都会说明它解锁了什么。只给它一个 URL 而什么都不给,你就能得到所有在未登录状态下加载的页面——对大多数应用来说,这已经是一套有用的测试套件了。
它整理出的所有内容都会作为工件保存在侧边栏中——项目地图、表单、测试计划、基线套件——这样重要的东西就不会埋在三层聊天记录之上。
或者留在你的编码代理里
应用只是入口之一,不是唯一入口。它做的每一件事都以类型化的 MCP 工具和 CLI 命令的形式提供,所以任何不想离开编辑器的人也不必离开:
pip install 'testtrout[mcp]'
trout mcp /path/to/your/project把你的代理指向 .claude/skills/ 中的技能,或者告诉它:
使用 TestTrout MCP 服务器。查看代码仓库,告诉我它还需要我提供什么,然后构建基线并运行它。
七个工具,绑定到一个项目上,这样代理就不会对错误的仓库采取行动:
| 阅读代码,询问部署,找出哪些是可测试的。 |
| 缺少哪些具体值;保存用户提供的内容。 |
| 现在可以测试什么,以及每个被阻塞的项需要什么。 |
| 编写基线并对照部署进行验证。 |
| 重新运行它,并读取每个测试在做什么。 |
另外还有 trout://map、trout://facts、trout://plan、trout://config、trout://scenarios 作为资源,这样大量状态就不会挤占代理的上下文窗口。
它能理解什么
trout look 在完全不访问网络的情况下读取代码,所以即使是你刚克隆的仓库也可以安全使用。在一个典型的 Supabase 应用上,它能发现:
表面 | 示例 |
页面 |
|
数据操作 |
|
RLS 策略 |
|
服务器动作 |
|
路由处理器 |
|
第三方服务 | Stripe、Resend——替换边界 |
模式 | 表、列、外键、RLS 状态 |
它还会告诉你,什么时候一个表是从浏览器代码写入的,且没有行级安全——这意味着任何人都可以通过 anon 密钥写入。这通常是个新闻。
它从不要求你的数据库
测试访问你的应用的方式和用户一样:通过 HTTP 访问你的端点,用真实浏览器访问你的界面。登录走的是你自己的登录表单,trout look 会定位一次,这样测试就能重放已知的表单,而不是去猜测。
所以整个事情只需要一个 URL 和两个测试账号。不需要 anon 密钥、不需要 service role、不需要项目凭据——没有任何大多数团队会合理拒绝交给测试工具的东西。
授权仍然被覆盖,而且可以说覆盖得更好:以两个普通账号登录,一个能看到的,另一个必须看不到。这既测试了你的策略,也测试了你的应用层在策略之上叠加的一切——这才是真实用户会遇到的东西。
为什么这些测试值得信任
它构建的是基线,而不是每个 PR 的猜测。 从你刚改的代码推导出的测试,断言新行为正确是构造性的——它无法捕捉回归。TestTrout 首先对照一个正在运行的部署来认证测试套件,所以失败意味着真有问题。
任何地方都没有模型。 扫描中没有、规划中没有、编写测试中也没有。每一条断言都追溯到部署实际做过的事情,这就是为什么相同的输入总是产生相同的测试套件,也是为什么不需要配置任何 API 密钥。
每条断言都带有其来源,在基线中它永远是 observed——证据就写在生成的文件里:
// observed: the page title when /orders was loaded
await expect(page).toHaveTitle('Orders');
// observed: seen on /orders at baseline
await expect(page.getByTestId('orders-table')).toBeVisible();它只发送 GET 请求。 端点测试重放探针发出的请求,无论端点声明了什么方法,所以把它指向生产环境也不会改变那里的任何东西。
失败在报告之前就被分类了。 只有 assertion_failure 是产品信号。认证失败、数据库不可达、第三方调用被阻断,这些都属于测试框架本身的问题,而且一次不确定的运行绝不会被升级为通过。
一切都可以从终端完成
trout add ~/code/my-app --url https://my-app.vercel.app
trout look # read the code, ask the deployment
trout facts # what I still need — all optional
trout build # write the baseline and prove it
trout run # re-run it; a failure means behaviour changed每条命令都支持 --json。完整教程见 docs/setup.md。
它如何存储数据
你的测试套件保留在你的代码仓库中,可提交、可审查:
.trout/scenarios/*.yaml what each test asserts, in plain language
.trout/facts.yaml what was asked for — never a secret value
.trout/plan.yaml what can be tested, and what is waiting
.trout/config.yaml deployments and env: references, never secrets
tests/trout/ generated Playwright and Vitest files运行历史、随时间变化的覆盖率,以及任务队列,都存放在 ~/.testtrout 下的 SQLite 中。这种拆分是刻意的:测试套件应该放在代码旁边,让拉取请求可以审查它;而文件无法回答的问题——这个测试是不是越来越不稳定、覆盖率是不是在上升——则属于数据库。
可选的 Web 视图
trout web覆盖率一目了然、排序后的差距列表、场景审查、带证据的运行历史、实时日志。与 CLI 使用相同的 .trout/ 文件——没有数据库、没有托管、仅回环。完全可选;CLI 和 MCP 本身已经完整。
安全性
这个工具需要你的数据库凭据,并且可以驱动你的部署,所以这些保证是在代码中强制执行的,而不是仅仅写在文档里:
生产环境默认只读。 变更请求在网络层被阻止,除非某个入口被明确标记为
disposable。这道防护位于导航之下,因为"只是加载一个页面就是只读的"这个说法是错的——很多这类应用在挂载时就会写入。没有任何代理,也没有任何网页点击,能改变这个设置。第三方服务被拦截。 一次测试运行不能扣款,也不能给客户发邮件。未匹配的出站请求会大声失败;一个静默匹配不到任何东西的 mock,正是测试套件显示绿色但实际上什么都没测的方式。
密钥不会进入已提交的文件。
.trout/config.yaml只包含env:引用。值存放在被 gitignore 的.env中。没有任何托管,也没有任何东西离开你的机器。 没有要调用的模型,没有要创建的账号。没有遥测。
支持的栈
React + Vite(Lovable、v0、Bolt)和 Next.js App Router,使用 TypeScript,搭配 Supabase,部署在任何可通过 HTTP 访问的地方。认证通过 Supabase、Clerk 或 NextAuth。
刻意保持狭窄。在一个栈上做深,胜过在多个栈上做浅——而且这些代码库足够规整,静态分析在它们上面是真正准确的。其他栈只需要一个适配器:见 docs/adapters.md。
路线图
✅ | 仓库分析、部署探测、差距排序 |
✅ | 场景编写、生成、执行、认证 |
✅ | MCP 服务器、CLI,以及带存储和 worker 的本地应用 |
✅ | 基于变更的测试选择、基分支差异 |
✅ | 多仓库:链接本地文件夹,或使用 GitHub token 克隆 |
✅ | 从界面或 CLI 进行完整配置,支持凭据发现 |
🔜 | GitHub 拉取请求检查 |
🔜 | 观察覆盖率索引(当前的选择使用声明覆盖率) |
贡献
添加一个框架、认证提供方或测试运行器,意味着实现一个协议并注册一个入口点——无需 fork。见 CONTRIBUTING.md 和 docs/adapters.md。
完整的测试套件在离线状态下运行,不需要 API 密钥。这是刻意的,值得保持。
许可证
Apache 2.0
This server cannot be deployed
Maintenance
Related MCP Connectors
MCP server for building and testing AI agents with multi-model experimentation and insights.
An MCP server that automatically collects feedback on your MCP server.
Official MCP server for Qase — manage test cases, runs, suites, defects via AI tools.
Mozark's MCP server for AI-powered app testing: device access, test automation, and QA insights.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceAn AI-powered MCP server that automates web testing workflows by enabling recording, execution, and discovery of tests through natural language prompts.66Apache 2.0
- AlicenseNot gradedqualityBmaintenanceMCP serverr for Lastest to manage your tests, AI create them, run them, and speed up AI-development.21Functional Source , Version 1.1, ALv2 Future
- AlicenseAqualityAmaintenanceAn MCP server that brings senior-QA discipline to AI coding assistants, enabling test planning, TDD, mutation testing, and code review.50411 PyPI7Apache 2.0
- AlicenseBqualityBmaintenanceAn MCP server for validating AI-generated code through automated browser testing, evidence collection, and intelligent diagnostics.10097 npm1MIT