Smithery Logo
MCPsSkillsDocsPricing
Login
Smithery Logo

Accelerating the Agent Economy

Resources

DocumentationPrivacy PolicySystem Status

Company

PricingAboutBlog

Connect

© 2026 Smithery. All rights reserved.

    hoblin

    rspec

    hoblin/rspec
    Coding
    13
    2 installs

    About

    SKILL.md

    Install

    Install via Skills CLI

    or add to your agent
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    ├─
    ├─
    └─

    About

    This skill should be used when the user asks to "write specs", "create spec", "add RSpec tests", "fix failing spec", or mentions RSpec, describe blocks, it blocks, expect syntax, test doubles, or...

    SKILL.md

    RSpec Testing

    This skill provides comprehensive guidance for writing effective RSpec tests in Ruby and Rails applications. Use for writing new specs, fixing failing tests, understanding matchers, using test doubles, and following RSpec best practices.

    Quick Reference

    Basic Structure

    RSpec.describe Order do
      subject(:order) { described_class.new(items) }
      let(:items) { [item1, item2] }
      let(:item1) { double("item", price: 10) }
      let(:item2) { double("item", price: 20) }
    
      describe "#total" do
        it "sums item prices" do
          expect(order.total).to eq(30)
        end
      end
    
      context "with discount" do
        let(:order) { described_class.new(items, discount: 5) }
    
        it "applies discount" do
          expect(order.total).to eq(25)
        end
      end
    end
    

    Key Concepts

    Concept Purpose
    describe / context Group related examples
    it / specify Define individual test cases
    let Lazy-evaluated, memoized helper
    let! Eager-evaluated helper (runs before each example)
    subject Primary object under test
    before / after Setup and teardown hooks
    expect Make assertions

    Writing Good Specs

    Use Named Subject for Method Tests

    describe "#calculate_total" do
      subject(:total) { order.calculate_total }
    
      it "returns sum of items" do
        expect(total).to eq(100)
      end
    end
    

    Context Blocks for Different States

    describe "#withdraw" do
      context "with sufficient funds" do
        let(:account) { build(:account, balance: 100) }
    
        it "reduces balance" do
          expect { account.withdraw(50) }.to change(account, :balance).by(-50)
        end
      end
    
      context "with insufficient funds" do
        let(:account) { build(:account, balance: 10) }
    
        it "raises error" do
          expect { account.withdraw(50) }.to raise_error(InsufficientFunds)
        end
      end
    end
    

    Common Matchers

    Equality

    expect(x).to eq(y)          # ==
    expect(x).to eql(y)         # eql? (type-sensitive)
    expect(x).to be(y)          # equal? (identity)
    

    Truthiness

    expect(x).to be_truthy      # not nil or false
    expect(x).to be_falsey      # nil or false
    expect(x).to be_nil
    expect(x).to be true        # exactly true
    

    Comparisons

    expect(x).to be > 3
    expect(x).to be_between(1, 10).inclusive
    expect(x).to be_within(0.1).of(3.14)
    

    Collections

    expect(arr).to include(1, 2)
    expect(arr).to contain_exactly(3, 2, 1)  # order-independent
    expect(arr).to all(be_positive)
    expect(str).to start_with("hello")
    expect(hash).to have_key(:name)
    

    Changes

    expect { x += 1 }.to change { x }.by(1)
    expect { x += 1 }.to change { x }.from(0).to(1)
    expect { user.save }.to change(User, :count).by(1)
    

    Errors

    expect { raise "boom" }.to raise_error
    expect { raise ArgumentError, "bad" }.to raise_error(ArgumentError, /bad/)
    

    Predicates (Dynamic)

    expect([]).to be_empty      # [].empty?
    expect(user).to be_valid    # user.valid?
    expect(hash).to have_key(k) # hash.has_key?(k)
    

    Test Doubles

    Types

    # Basic double (strict)
    user = double("user", name: "Bob")
    
    # Verifying doubles (recommended)
    user = instance_double("User", name: "Bob")  # validates instance methods
    api = class_double("Api", fetch: data)       # validates class methods
    logger = object_double(Rails.logger)         # validates object methods
    
    # Spy (null object for after-the-fact verification)
    notifier = spy("notifier")
    

    Stubbing

    allow(user).to receive(:name).and_return("Bob")
    allow(Api).to receive(:fetch).and_return(data)
    allow(obj).to receive(:method) { computed_value }
    

    Expectations

    expect(user).to receive(:save).and_return(true)
    expect(Api).to receive(:post).with(hash_including(id: 1))
    
    # Spy pattern (verify after action)
    notifier = spy("notifier")
    service.call(notifier)
    expect(notifier).to have_received(:notify).with("done")
    

    Argument Matchers

    expect(obj).to receive(:call).with(anything)
    expect(obj).to receive(:call).with(kind_of(Integer))
    expect(obj).to receive(:call).with(hash_including(a: 1))
    expect(obj).to receive(:call).with(array_including(1, 2))
    

    Rails Specs

    Spec Type Use For Key Helpers
    type: :model Business logic, scopes, validations build, create, associations
    type: :request Controller actions (preferred) get, post, response, have_http_status
    type: :system Browser/UI testing visit, fill_in, click_button, have_text
    type: :job Background jobs have_enqueued_job, perform_now
    type: :mailer Email delivery have_enqueued_mail, deliver_now
    type: :routing Route resolution route_to, be_routable

    See examples/rails/ for complete spec templates.

    Best Practices

    Do

    • Use described_class instead of hardcoding class name
    • Use let for test data, let! when database records must exist before test
    • Use named subject when referencing in tests: subject(:user) { ... }
    • Use context blocks to organize different scenarios
    • Use verifying doubles (instance_double) over plain double
    • Name examples with verbs: it "creates user" not it "should create user"
    • Keep examples focused on one behavior
    • Use factories over fixtures for flexible test data
    • Prefer build_stubbed or build over create when database not needed

    Don't

    • Don't use instance variables (@user) - use let for type safety
    • Don't use before just to trigger let evaluation - use let! instead:
      # BAD - before just to initialize
      let(:user) { create(:user) }
      before { user }
      
      # GOOD - let! for eager evaluation
      let!(:user) { create(:user) }
      
      Use before for side-effects like sign_in(user) or driven_by(:rack_test)
    • Don't use let! when let suffices (wastes resources)
    • Don't test Rails framework (validations work, focus on business logic)
    • Don't stub the object under test
    • Avoid any_instance_of - prefer stubbing ClassName.new to return a double (see references/mocks.md)
    • Don't use receive_message_chain (violates Law of Demeter)
    • Don't write examples without descriptions
    • Shared examples work best for testing concerns across including classes. For unique behaviors, prefer repetition over abstraction

    Factory Bot

    # Build strategies
    user = build(:user)              # In-memory, not persisted
    user = create(:user)             # Persisted to database
    user = build_stubbed(:user)      # Fake persisted (fastest)
    attrs = attributes_for(:user)    # Hash of attributes
    
    # With traits and attributes
    user = create(:user, :admin, :verified, name: "Bob")
    
    # Lists
    users = create_list(:user, 5, :admin)
    

    Strategy Selection:

    • build_stubbed - Unit tests without database (fastest)
    • build - Validation tests, method tests
    • create - Database queries, scopes, associations
    • attributes_for - Controller params

    See references/factory_bot.md for traits, sequences, associations, and callbacks.

    Configuration

    Essential settings for spec_helper.rb and rails_helper.rb:

    Setting Purpose
    verify_partial_doubles = true Validates stubbed methods exist
    filter_run_when_matching :focus Run only focused specs (fit, fdescribe)
    order = :random Randomize spec order to catch dependencies
    use_transactional_fixtures = true Rollback database after each spec
    infer_spec_type_from_file_location! Auto-detect spec type from path

    See examples/core/configuration.rb for complete setup.

    Before You Write

    What are you about to do?

    ├── Creating or modifying a factory?
    │   └── Read `references/factory_bot.md`
    │
    ├── Writing a new spec file?
    │   ├── Model/service/PORO → Read `references/core.md`
    │   ├── Request/controller → Read `references/rails.md`
    │   └── System/feature/job/mailer → Read `references/rails.md`
    │
    ├── Using test doubles, stubs, or mocks?
    │   └── Read `references/mocks.md`
    │
    ├── Writing custom or complex matchers?
    │   └── Read `references/matchers.md`
    │
    └── Fixing a failing spec?
        ├── Factory-related error → Read `references/factory_bot.md`
        ├── Mock/stub error → Read `references/mocks.md`
        ├── Matcher error → Read `references/matchers.md`
        └── Rails-specific error → Read `references/rails.md`
    

    Need code examples?

    ├── Basic spec structure, hooks, shared examples
    │   └── See `examples/core/`
    │
    ├── Matcher usage patterns
    │   └── See `examples/matchers/`
    │
    ├── Test doubles and stubbing
    │   └── See `examples/mocks/`
    │
    ├── Rails spec templates (model, request, system, job, mailer)
    │   └── See `examples/rails/`
    │
    └── Factory definitions with traits and associations
        └── See `examples/factory_bot/`
    

    Running Specs

    rspec                           # all specs
    rspec spec/models               # directory
    rspec spec/user_spec.rb         # file
    rspec spec/user_spec.rb:23      # line
    rspec --format doc              # documentation format
    rspec --only-failures           # re-run failures
    rspec --profile 10              # show slowest
    

    Debugging

    rspec --seed 12345              # reproduce random order
    rspec --fail-fast               # stop on first failure
    rspec --backtrace               # full backtrace
    
    Recommended Servers
    Postman
    Postman
    Google Docs
    Google Docs
    vastlint - IAB XML VAST validator and linter
    vastlint - IAB XML VAST validator and linter
    Repository
    hoblin/claude-ruby-marketplace
    Files