mcpField
R
rspec-coder

rspec-coder

github.com/majesticlabs-devテスト・品質5055 回インストール7 週間前に更新
リポジトリ

rspec-coder について

RSpecテストを書く開発者向けのスキルで、Railsプロジェクトの規約や、spec、fixture、マッチャー、モックの使い方を示します。振る舞いを検証する独立したテストと、正常系・境界ケースの網羅を重視します。

主な機能

  1. 01AAA構成と振る舞い重視のテスト
  2. 02RSpecのファイル構成と命名規約
  3. 03fixture、subject、letの使い方
  4. 04モック、スタブ、マッチャーの例
  5. 05Railsの主要コンポーネント向けカバレッジ指針

活用シーン

  1. 01明確なコンテキストを備えたモデルやサービスのspec作成
  2. 02スタブと呼び出し期待値による外部処理のテスト
  3. 03Shoulda Matchersによるバリデーションと関連の確認
  4. 04エラーケースや境界ケースの網羅性の確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/majesticlabs-dev/majestic-marketplace --skill rspec-coder

インストール後、Claude Code で/rspec-coderを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
anti-patterns.md
matchers.md
patterns.md

詳細

RSpec コーダー

基本理念

  • AAA パターン:明確にするため、Arrange-Act-Assert 構造にします
  • 実装より振る舞いを重視:コードの仕組みではなく、動作をテストします
  • 分離:テストは互いに独立させます
  • 説明的な名前:ブロックの名前から振る舞いが明確に分かるようにします
  • 網羅性:正常系とエッジケースの両方をテストします
  • 高速なテスト:データベース操作を最小限に抑えます
  • フィクスチャ:共通のデータ設定にはフィクスチャを使います
  • Shoulda Matchers:バリデーションとアソシエーションにはこれを使います

重要な規約

❌ require 'rails_helper' を追加しない

RSpec は .rspec 設定を通じて読み込まれます。手動で追加するのは冗長です。

# ✅ GOOD - no require needed
RSpec.describe User do
  # ...
end
❌ 冗長なスペックタイプを追加しない

RSpec はファイルの場所からタイプを自動的に推測します。

# ✅ GOOD - type inferred from spec/models/ location
RSpec.describe User do
  # ...
end
✅ 先頭に :: を付けずに名前空間を使う
# ✅ GOOD - no leading double colons
RSpec.describe DynamicsGp::ERPSynchronizer do
  # ...
end

テストの構成

ファイル構成
  • spec/models/ - モデルの単体テスト
  • spec/services/ - サービスオブジェクトのテスト
  • spec/controllers/ - コントローラーのテスト
  • spec/requests/ - リクエストスペック(API テスト)
  • spec/mailers/ - メーラーのテスト
  • spec/jobs/ - バックグラウンドジョブのテスト
  • spec/fixtures/ - テストデータ
  • spec/support/ - ヘルパーモジュールと共有サンプル
  • spec/rails_helper.rb - Rails 固有の設定
describe と context の使い方
ブロック用途例
describeメソッド/クラスごとにグループ化describe "#process"
context条件ごとにグループ化context "when user is admin"
RSpec.describe OrderProcessor do
  describe "#process" do
    context "with valid payment" do
      # success tests
    end

    context "with invalid payment" do
      # failure tests
    end
  end
end

Subject と Let

詳しい例については、references/patterns.md を参照してください。

パターン使用例
subject(:name) { ... }テスト対象の主要なオブジェクト/メソッド
let(:name) { ... }遅延評価されるメモ化データ
let!(:name) { ... }即時評価(各テストの前)
RSpec.describe User do
  describe "#full_name" do
    subject(:full_name) { user.full_name }
    let(:user) { users(:alice) }

    it { is_expected.to eq("Alice Smith") }
  end
end

フィクスチャ

詳しい例については、references/patterns.md を参照してください。

# spec/fixtures/users.yml
alice:
  name: Alice Smith
  email: [email protected]
  admin: false
RSpec.describe User do
  fixtures :users

  it "validates email" do
    expect(users(:alice)).to be_valid
  end
end

モックとスタブ

詳しい例については、references/patterns.md を参照してください。

メソッド用途
allow(obj).to receive(:method)戻り値をスタブ化する
expect(obj).to receive(:method)呼び出しが行われることを検証する
# Stubbing external service
allow(PaymentGateway).to receive(:charge).and_return(true)

# Verifying method called
expect(UserMailer).to receive(:welcome_email).with(user)

マッチャー早見表

完全なリファレンスについては、references/matchers.md を参照してください。

必須のマッチャー
# Equality
expect(value).to eq(expected)

# Truthiness
expect(obj).to be_valid
expect(obj).to be_truthy

# Change
expect { action }.to change { obj.status }.to("completed")
expect { action }.to change(Model, :count).by(1)

# Errors
expect { action }.to raise_error(SomeError)

# Collections
expect(array).to include(item)
expect(array).to be_empty
Shoulda Matchers
# Validations
it { is_expected.to validate_presence_of(:name) }
it { is_expected.to validate_uniqueness_of(:email) }

# Associations
it { is_expected.to have_many(:posts) }
it { is_expected.to belong_to(:account) }

AAA パターン

すべてのテストを Arrange-Act-Assert の構造にします。

describe "#process_refund" do
  subject(:process_refund) { processor.process_refund }

  let(:order) { orders(:completed_order) }
  let(:processor) { described_class.new(order) }

  it "updates order status" do
    process_refund  # Act
    expect(order.reload.status).to eq("refunded")  # Assert
  end

  it "credits user account" do
    expect { process_refund }  # Act
      .to change { order.user.reload.account_balance }  # Assert
      .by(order.total)
  end
end

テストカバレッジの基準

テスト対象
種類テスト項目
モデルバリデーション、アソシエーション、スコープ、コールバック、メソッド
サービス正常系、異常系、エッジケース、外部連携
コントローラーステータスコード、レスポンス形式、認証、リダイレクト
ジョブ実行、再試行ロジック、エラー処理、冪等性
カバレッジの例
RSpec.describe User do
  fixtures :users

  describe "validations" do
    subject(:user) { users(:valid_user) }

    it { is_expected.to validate_presence_of(:name) }
    it { is_expected.to validate_presence_of(:email) }
    it { is_expected.to validate_uniqueness_of(:email).case_insensitive }
  end

  describe "associations" do
    it { is_expected.to have_many(:posts).dependent(:destroy) }
  end

  describe "#full_name" do
    subject(:full_name) { user.full_name }
    let(:user) { User.new(first_name: "Alice", last_name: "Smith") }

    it { is_expected.to eq("Alice Smith") }

    context "when last name is missing" do
      let(:user) { User.new(first_name: "Alice") }
      it { is_expected.to eq("Alice") }
    end
  end
end

アンチパターン

詳しい例については、references/anti-patterns.md を参照してください。

アンチパターン問題点
require 'rails_helper'冗長で、.rspec を通じて読み込まれる
type: :model冗長で、ファイルの場所から推測される
名前空間の先頭に :: を付けるRuboCop のスタイルに反する
空のテスト本体誤った安心感を与える
プライベートメソッドをテストする実装に依存してしまう
フィクスチャを使わないテストが遅くなる
shoulda を使わないバリデーションのテストが冗長になる

ベストプラクティスのチェックリスト

重要な規約:

  • require 'rails_helper' を追加しない
  • 冗長なスペックタイプを追加しない
  • 先頭に :: を付けずに名前空間を使う

テストの構成:

  • メソッド/クラスには describe を使う
  • 条件には context を使う
  • ネストは最大 3 階層にする

テストデータ:

  • フィクスチャを使う(ファクトリーではなく)
  • 遅延データには let を使う
  • テスト対象のメソッドには subject を使う

アサーション:

  • バリデーションには Shoulda matchers を使う
  • アソシエーションには Shoulda matchers を使う
  • 状態の変化には change マッチャーを使う

カバレッジ:

  • 正常系をテストする
  • 異常系をテストする
  • エッジケースを網羅する

クイックリファレンス

# Minimal spec file
RSpec.describe User do
  fixtures :users

  describe "#full_name" do
    subject(:full_name) { user.full_name }
    let(:user) { users(:alice) }

    it { is_expected.to eq("Alice Smith") }
  end

  describe "validations" do
    subject(:user) { users(:alice) }

    it { is_expected.to validate_presence_of(:name) }
    it { is_expected.to have_many(:posts) }
  end
end

コメント