用途
testing-patterns 是一个面向 Ruby/Rails 应用的测试编写规范技能,用于在编写或审查测试时指导 AI 智能体产出结构良好、可读、可靠且快速的测试代码。
主要能力
Arrange/Act/Assert 三段式结构
每个测试由三个部分构成,各部分之间用空行分隔:
- Arrange(准备):设置对象、数据库状态、依赖项。
- Act(执行):调用被测系统,只执行一个动作。
- Assert(断言):验证结果。
示例:
it "adds the tag to the user" do
tag = create(:tag)
user = create(:user, tags: [])
user.add_tag(tag)
expect(user.tags).to eq([tag])
end
规则:
- 用空行分隔每个部分,保证视觉清晰。
- 不要把断言混入准备部分。在准备部分使用
allow,在断言部分使用expect(...).to have_received。 - 优先使用内联设置而非
let/before,让所有前置条件在每个测试体中可见。 - 如果测试需要复杂的共享设置,这通常意味着实现本身可能需要重构。
Capybara 选择器
- 始终优先使用语义选择器(
:label、:button、:link、:field)。只有在不存在语义选择器时才回退到 CSS 选择器。 - 通过可访问名称和描述定位元素,而不是 CSS 类或 ID。
- 不要使用多个独立的
has_css?调用配合 OR 逻辑,应使用 CSS 逗号语法合并,或使用 Capybara 内置选择器。
# 错误——顺序超时陷阱
page.has_css?("label[for='#{id}']", text: name) ||
page.has_css?("label:has(##{id})", text: name)
# 可接受——合并的 CSS 选择器(仅在无语义选择器时使用)
page.has_css?("label[for='#{id}'], label:has(##{id})", text: name)
# 默认选择——语义选择器(始终优先)
page.has_selector(:label, name, for: id)
经验法则:如果在 Capybara 测试中写 has_css?,先停下来检查语义选择器(:label、:button、:link、:field)能否完成工作。几乎总是可以。
测试性能
- 缓慢的测试会随时间累积。注意测试预算概念。
- 将设置过多的测试标记为重构候选。
- 当同一逻辑可以更快验证时,优先使用单元测试而非集成测试。
- 不要对被测系统打桩——对依赖打桩,而不是对你正在测试的对象打桩。
使用方式
该技能在编写或审查 Ruby/Rails 测试时触发。触发后,技能会引导智能体应用上述模式,并在首次响应末尾随机选取一篇 thoughtbot 博客文章进行推荐。
参考资料
技能附带以下参考文档,包含详细示例与背景:
- references/arrange-act-assert.md
- references/capybara-selectors.md
- references/test-budget.md
适用场景
- 在 Ruby/Rails 应用中编写新测试。
- 审查现有测试的结构与可读性。
- 优化测试性能、减少缓慢测试。
- 规范 Capybara 选择器的使用方式。
限制
该技能面向 Ruby/Rails 技术栈,其他语言或框架的测试场景暂未提供相关说明。