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 matchers. Should also be used when editing *_spec.rb files, working in spec/ directory, planning implementation phases that include tests (TDD/RGRC workflow), writing Testing Strategy or Success Criteria sections, discussing unit or integration tests, or reviewing spec output and test failures. Comprehensive RSpec and FactoryBot reference with best practices, ready-to-use patterns, and examples.
View on GitHubFebruary 1, 2026
Select agents to install to:
npx add-skill https://github.com/hoblin/claude-ruby-marketplace/blob/main/plugins/rspec/skills/rspec/SKILL.md -a claude-code --skill rspecInstallation paths:
.claude/skills/rspec/# 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
```ruby
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
```ruby
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
```ruby
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
```ruby
expect(x).to eq(y) # ==
expect(x).to eql(y) # eql