mcpField
T
test-service

test-service

github.com/igmarin测试与质量2840 次安装4 周前更新
代码仓库

关于 test-service

用于编写服务对象 RSpec 测试的技能,涵盖隔离、集成测试设置和覆盖范围规范,适合在实现前验证服务行为并检查回归。

主要功能

  1. 01服务测试结构与 subject
  2. 02使用 instance_double 隔离依赖
  3. 03数据库集成测试设置
  4. 04API 响应哈希工厂
  5. 05错误与边界情况清单

适用场景

  1. 01测试服务对象的正常与失败路径
  2. 02在单元测试中隔离服务依赖
  3. 03检查服务测试的覆盖缺口

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/igmarin/rails-agent-skills --skill test-service

安装后在 Claude Code 中输入/test-service确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

PATTERNS.md
assets/
spec_examples.md
testing_checklist.md

详细介绍

测试服务

快速参考

方面规则
文件位置spec/services/module_name/service_spec.rb
Subjectsubject(:service_call) { described_class.call(params) }
单元隔离协作者使用 instance_double
集成数据库测试使用 create
多重断言aggregate_failures
状态验证change 匹配器
时间相关travel_to
API 响应FactoryBot hash 工厂(class: Hash)

HARD-GATE

DO NOT implement the service before step 1 is written and failing for the right reason.
1. WRITE:   Write the spec (happy path + error cases + edge cases)
2. RUN:     bundle exec rspec spec/services/your_service_spec.rb
3. VERIFY:  Confirm failures are for the right reason (not a typo or missing factory)
4. FIX:     Implement or fix until the spec passes
5. SUITE:   bundle exec rspec spec/services/ — verify no regressions

核心流程

Spec 模板
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe ModuleName::MainService do
  describe '.call' do
    subject(:service_call) { described_class.call(params) }

    let(:shelter) { create(:shelter, :with_animals) }
    let(:params) do
      { shelter: { shelter_id: shelter.id }, items: %w[TAG001 TAG002] }
    end

    context 'when input is valid' do
      before { create(:animal, tag_number: 'TAG001', shelter:) }

      it 'returns success' do
        expect(service_call[:success]).to be true
      end
    end

    context 'when shelter is not found' do
      let(:params) { super().merge(shelter: { shelter_id: 999_999 }) }

      it 'returns error response' do
        expect(service_call[:success]).to be false
      end
    end

    context 'when input is blank' do
      let(:params) { { shelter: { shelter_id: nil }, items: [] } }

      it 'returns error response with meaningful message' do
        aggregate_failures do
          expect(service_call[:success]).to be false
          expect(service_call[:errors]).not_to be_empty
        end
      end
    end
  end
end

使用 instance_double 实现单元隔离:

let(:client) { instance_double(Api::Client) }
before { allow(client).to receive(:execute_query).and_return(api_response) }

关键 — 协作者必须通过 instance_double 进行 stub。三种模式:

  • 注入依赖: 直接在 params 中传入 double。
  • Stub .new: 当服务内部实例化时,使用 allow(CarrierApi::Client).to receive(:new).and_return(client)。
  • 避免类级别 stub: 不要使用 allow(CarrierApi::Client).to receive(:notify) — 始终对实例进行 double。

集成测试使用 create:

let(:source_shelter) { create(:shelter, :with_animals) }
用于 API 响应的 FactoryBot Hash 工厂

测试 API 客户端时,使用 class: Hash 配合 initialize_with 来构建 hash 形态的响应 fixture。一个最小示例:

FactoryBot.define do
  factory :api_animal_response, class: Hash do
    tag_number { 'TAG001' }
    status     { 'active' }

    initialize_with { attributes.stringify_keys }
  end
end

# In the spec:
let(:api_response) { build(:api_animal_response, tag_number: 'TAG002') }
新测试文件检查清单
  • 为主要操作定义了 subject
  • 单元测试用 instance_double / 集成测试用 create
  • 每个公共方法的正常路径
  • 错误与边界情况(空输入、无效引用、失败)
  • 在相关情况下覆盖部分成功场景
  • 对重复模式使用 shared_examples
  • 多重断言测试使用 aggregate_failures
  • 状态验证使用 change 匹配器
常见错误
错误正确做法
没有错误场景测试始终在正常路径之外测试失败情况
到处使用 let!除非该值在 setup 中无条件必需,否则使用 let(惰性求值)
庞大的工厂设置保持工厂最小化 — 只包含测试所需的属性
重构时行为未变但 spec 失败重构时失败的测试是在测试内部实现,而非契约

扩展资源(渐进式披露)

仅在需要其特定内容时加载这些文件:

输出风格

完成服务测试时,输出必须包含:

# Service Spec — [ServiceName]

## Spec File
- Path: spec/services/<module>/<service>_spec.rb
- Subject: `described_class.call(params)`

## Coverage
- Happy path: ✓ (<n> examples)
- Error cases: ✓ (<n> examples — list error classes/conditions)
- Edge cases: ✓ (<n> examples — blank input, boundary values)
- Isolation: instance_double for <collaborator list>

## TDD Gate
- RED: <failure message confirming missing behavior>
- GREEN: <all examples pass>
- Suite: <full spec/services/ suite status>

集成

技能何时串联
write-tests用于通用 RSpec 风格和 TDD 纪律
create-service-object用于被测试的服务约定
integrate-api-client用于 API 客户端层测试模式
test-engine当测试引擎特定的服务时

评论

支持 Markdown