rspec-coder について
RSpecテストを書く開発者向けのスキルで、Railsプロジェクトの規約や、spec、fixture、マッチャー、モックの使い方を示します。振る舞いを検証する独立したテストと、正常系・境界ケースの網羅を重視します。
主な機能
- 01AAA構成と振る舞い重視のテスト
- 02RSpecのファイル構成と命名規約
- 03fixture、subject、letの使い方
- 04モック、スタブ、マッチャーの例
- 05Railsの主要コンポーネント向けカバレッジ指針
活用シーン
- 01明確なコンテキストを備えたモデルやサービスのspec作成
- 02スタブと呼び出し期待値による外部処理のテスト
- 03Shoulda Matchersによるバリデーションと関連の確認
- 04エラーケースや境界ケースの網羅性の確認
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ majesticlabs-dev/ majestic-marketplace --skill rspec-coderインストール後、Claude Code で/rspec-coderを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/anti-patterns.mdmatchers.mdpatterns.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
コメント
Markdown 対応