用途
plan-tests 是一个面向 Rails 项目的测试规划技能,用于在实施 Rails 变更时决定“第一个失败的测试用例”(first failing spec)应该写什么、写在哪里。它的核心理念是:一个最小示例就足以打开测试之门(One minimal example opens the gate),从而进入 TDD 循环。
该技能适用于需要确定测试切入点的场景,触发词包括:first failing test、what test first、TDD、spec 等。
主要能力
快速参考表
技能提供一张映射表,根据变更类型推荐首个 spec 类型、路径及理由:
- API 契约、参数、状态码、JSON 结构 → Request spec,路径
spec/requests/,理由:证明真实的 HTTP 契约。 - 聚合记录或值对象上的领域规则 → Model spec,路径
spec/models/,理由:对领域行为提供快速反馈。 - 跨协作者的多步骤编排 → Service spec,路径
spec/services/,理由:聚焦工作流边界。 - 入队/运行/重试/丢弃行为 → Job spec,路径
spec/jobs/,理由:直接捕获异步语义。 - 关键 Turbo/Stimulus 或浏览器可见流程 → System spec,路径
spec/system/,理由:仅当浏览器交互是真正风险时使用。 - 引擎路由、生成器、宿主集成 → Engine spec,路径
spec/requests/或引擎路径,理由:普通应用 spec 会遗漏引擎接线,参见 test-engine。 - Bug 修复 → 复现 spec,路径为观察到 bug 的位置,理由:证明修复并防止回归。
硬性检查点:测试设计评审
在编写失败 spec 后,技能要求进行测试设计评审,展示已编写的失败 spec,并询问:
- 该测试是否覆盖了正确的行为?
- 边界是否正确(request vs service vs model)?
- 是否代表了最重要的边缘情况?
- 失败原因是否正确(功能缺失,而非设置错误)?
确认:在测试设计满足已接受的要求且观察到 RED(失败)后,方可继续。
使用方式
核心流程
从能证明行为且所需不必要设置最少的高价值边界开始。
步骤:
- 命名行为:陈述要证明的用户可见结果或不变量。
- 定位边界:决定行为首先在哪里被观察到——HTTP 请求、服务入口点、模型规则、任务执行、引擎集成或外部适配器。使用快速参考表将变更类型映射到正确的 spec 类型。
- 编写一个失败示例:保持最小化;一个示例足以打开大门。将其他用例列为后续覆盖。
- 建议路径:使用常规 Rails 约定命名可能的 spec 路径(例如
spec/requests/...、spec/services/...、spec/jobs/...、spec/models/...)。 - 运行并验证:确认失败是因为行为缺失,而不是因为设置损坏。
- 交接:继续使用适合该切片的技能——
write-tests用于通用 spec 编写,test-service用于服务层覆盖,或test-engine用于引擎集成。
示例
好的示例:新的 JSON 端点
# Behavior: POST /orders validates params and returns 201 with JSON payload
# First slice: request spec
# Suggested path: spec/requests/orders/create_spec.rb
RSpec.describe "POST /orders", type: :request do
let(:user) { create(:user) }
let(:valid_params) { { order: { product_id: create(:product).id, quantity: 1 } } }
before { sign_in user }
it "creates an order and returns 201" do
post orders_path, params: valid_params, as: :json
expect(response).to have_http_status(:created)
expect(response.parsed_body["id"]).to be_present
end
end
好的示例:新的编排服务
# Behavior: Orders::CreateOrder validates inventory, persists, and enqueues follow-up work
# First slice: service spec
# Suggested path: spec/services/orders/create_order_spec.rb
RSpec.describe Orders::CreateOrder do
subject(:result) { described_class.call(user: user, product: product, quantity: 1) }
let(:user) { create(:user) }
let(:product) { create(:product, stock: 5) }
it "returns a successful result with the new order" do
expect(result).to be_success
expect(result.order).to be_persisted
end
end
常见陷阱
- 因为 PORO spec 容易就先用它:容易 ≠ 高信号——选择能证明真实行为的边界。
- 在运行任何测试之前就写三种 spec 类型:选择一个切片,运行它,证明失败,然后继续。
- 对所有事情都默认使用一种 spec 类型:将 spec 类型与真实风险所在的层匹配(HTTP、领域、异步、浏览器)。
- 过早跳到 system spec:保留给下层无法证明的关键浏览器流程。
扩展资源(渐进式披露)
仅在需要其特定内容时加载这些文件:
assets/first_slice_template.md— 在记录测试计划时使用;提供行为、边界决策、开门 spec 和后续覆盖的结构化模板。
输出风格
完成测试规划时,生成简要的结构化摘要,并使用 assets/first_slice_template.md 填充完整计划。摘要必须涵盖:
- Behavior — 正在证明的用户可见结果
- First Slice — spec 类型、文件路径和边界理由
- Opening Gate — 预期的 RED 失败消息,并确认失败原因是“功能缺失,而非设置错误”
- Follow-up Coverage — 从初始门禁推迟的额外用例的要点列表
- Design Checkpoint — 确认行为、边界、边缘情况和失败原因均已验证
适用场景
- Rails 项目中进行 TDD 开发,需要确定第一个失败测试。
- 面对多种测试类型(request、model、service、job、system、engine)时,需要根据变更类型选择正确的测试边界。
- Bug 修复时,需要编写复现 spec 来证明修复并防止回归。
- 需要结构化测试计划模板来记录行为、边界决策和后续覆盖。
限制
- 该技能专注于 Rails 项目,依赖 RSpec 测试框架。
- 快速参考表覆盖的变更类型有限,未列出的变更类型可能需要自行判断。
- 技能本身不执行测试,仅提供规划指导;实际运行和验证需开发者自行完成。
- 扩展资源文件需要按需加载,未提供时无法使用模板。
- 关于收费、价格、平台支持等具体信息暂未提供。