关于 patrol-write-test
patrol-write-test 是用于编写和完善 Patrol 测试的 Agent 技能。它指导测试人员复用现有代码、分配控件键、逐步编写和运行测试,并遵循 Patrol 的交互与断言规则。
主要功能
- 01检查并复用现有测试代码
- 02在测试文件中直接编写 Patrol 操作
- 03分配唯一的控件键
- 04通过 Patrol MCP 逐步运行测试
- 05处理原生对话框和权限
适用场景
- 01为新的应用流程添加测试
- 02通过截图排查 Patrol 测试失败
- 03为测试涉及的控件添加键
MCP 相关
该技能要求 Agent 使用 Patrol MCP 工具运行单项测试、查看状态和 UI 树、截取屏幕截图并退出会话。
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ leancodepl/ patrol --skill patrol-write-test安装后在 Claude Code 中输入/patrol-write-test确认已加载。
详细介绍
如果项目的 Patrol 测试使用 LeanCode 的 Modules/System/ApiClients 架构(例如,包含 patrol_test/modules/ 目录和 testApp 封装),还应遵循 patrol-test-architecture。该规范基于本技能构建,若两者存在差异,以该规范为准。
编写新测试时的操作顺序
- 检查现有测试代码中可复用的函数
- 同时考虑是否可以调整现有函数,使其适用于原有用法和新测试
- 如果必需元素尚未分配测试键,则为其分配测试键
- 开始编写测试:复用现有函数,并将新的测试步骤放入新测试文件
- 直接在测试文件中编写 Patrol 操作,不要创建新方法
- 开发过程中频繁运行测试,不要等到完整测试写完后才运行。每完成一组逻辑步骤后就运行测试,以便及早发现失败
- 完整测试通过后,将新代码整理为可复用函数
- 整理后重新运行测试,确认其仍然通过
Patrol MCP 用法
使用 Patrol 测试时:
- 使用
patrol-run({ "testFile": "patrol_test/your_test.dart" })运行测试并等待完成 - 如果没有正在运行的会话:使用指定的测试文件启动新会话
- 如果已有会话正在运行:自动重启当前测试
- 使用
patrol-screenshot({ "platform": "android" })或patrol-screenshot({ "platform": "ios" })截取屏幕截图,以便调试测试失败 - 使用
patrol-quit({})正常退出会话 - 使用
patrol-status({})检查当前状态和最近的输出 - 使用
patrol-native-tree({})获取当前原生 UI 树层级,以便编写原生交互以及与被测应用之外的应用进行交互。
Patrol 测试规则
Patrol API
- 任何直接使用 Patrol API(
$()、.scrollTo()、.tap()、.enterText()、.waitUntilVisible()等)的文件,都应添加import 'package:patrol/patrol.dart'; - 实现测试操作前,务必检查 Patrol API:
- 在代码库中搜索现有的 Patrol API 用法
- 检查针对特定操作的 $.platform API
- 如果在代码库中找不到相应方法,请查阅:https://patrol.leancode.co/
- 确认正确的 API 方法后再实现
- 实现测试操作前,务必检查
$.platform方法 - 不要使用 flutter_test 包。只能使用 Patrol API
- 单个测试只能通过 Patrol MCP 服务运行,所有测试使用
patrol test运行。绝不要使用flutter test命令 - 不要自行编写 patrolSetUp 和 patrolTearDown 方法
操作规则
- 点击、滚动到目标位置和输入文本之前或之后,不要使用
$.pump、waitUntilVisible、waitUntilExists或其他等待方法。Patrol 会自动处理。只在测试末尾使用这些方法 - 查找 Widget 时只能使用键
- 除非绝对必要,否则不要编写 try catch 块
- 编写测试后,通过 MCP 服务运行测试以检查是否有效;如果失败,则修复
- 如果测试因找不到元素而失败,请检查应用代码中是否需要滚动到该元素,并在必要时调整测试
断言规则
- 不要在操作后编写断言,但应在测试末尾编写断言
- 优先在测试末尾使用
waitUntilVisible作为断言 - 只有在
waitUntilVisible不够用时,才使用expect()进行断言
原生对话框处理
- 始终处理流程中出现的原生对话框:
- 在触发对话框的操作后立即处理对话框
- 对于原生权限,优先使用
$.platform.mobile.grantPermissionWhenInUse,而不是$.platform.mobile.tap
测试键
-
仅为参与测试的组件分配键
-
仅向现有组件添加
key参数 -
绝不更改组件签名
-
绝不重构现有代码结构
-
绝不在应用中硬编码键,必须使用应用和测试共用的键文件中的键
-
绝不在应用中创建新组件
-
绝不创建未分配给组件的键
-
始终确保每个键值都是唯一的
-
始终按字母顺序排列键
-
将键作为组件构造函数的第一个参数
-
如果组件不唯一(例如由列表生成),请使用参数化键
- 如果已有枚举或 DTO,始终优先将其用作参数
- 使用现有组件属性作为参数化键的参数
- 绝不在应用中分配参数化键,却在键文件中为其使用固定值(反之亦然)
- 绝不创建辅助方法,改用参数化键
- 组件由现有枚举或 DTO 生成时,始终使用参数化键,并将相应的枚举或 DTO 值作为参数
在以下情况下使用独立键:
- 组件是硬编码的,且在编译时已知
- 组件有明确且有意义的名称
在以下情况下使用参数化键:
- 组件由动态数据生成
- 组件由 DTO 或枚举生成
- 组件数量可变或较多
- 组件在循环中或从列表中生成
评论
支持 Markdown