.cursor/skills/ruby/rspec/SKILL.md
RSpec best practices from the RSpec Style Guide and Better Specs. Use when writing or reviewing RSpec specs in Ruby projects.
npx skillsauth add shubhamtaywade82/repocontext rspecInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill applies the RSpec Style Guide and Better Specs. RuboCop RSpec enforces many of these rules.
Use when writing or reviewing RSpec examples, model specs, or integration tests.
describe/context/feature opening — start the block body immediately.describe/context blocks; none after the last block in a group.subject, let, and before/after blocks.subject and let blocks together; separate them from before/after with a blank line.it/specify block to separate expectations from context.# good
describe Article do
subject { FactoryBot.create(:article) }
let(:user) { FactoryBot.create(:user) }
before do
# ...
end
describe '#summary' do
context 'when there is a summary' do
it 'returns the summary' do
# ...
end
end
context 'when there is no summary' do
it 'returns nil' do
# ...
end
end
end
end
subject, then let!/let, then before/after. Put subject first when used.context to group examples. Start with when, with, or without. Prefer having a matching negative case (e.g. "when X" and "when not X").let for data shared across examples; use let! when the value must exist before the example runs (e.g. for scopes). Prefer let over instance variables (@var).shared_examples / it_behaves_like to DRY repeated behavior. Don't over-DRY early; duplication in specs is acceptable for clarity.:each (it's the default). Use :context instead of :all when you need scope; avoid before(:context) when possible (state leakage).it in iterators: Don't generate examples in a loop; write each describe/it explicitly so changes are localized.# bad
[:new, :show, :index].each do |action|
it 'returns 200' do
get action
expect(response).to be_ok
end
end
# good – separate describe per action
describe 'GET new' do
it 'returns 200' do
get :new
expect(response).to be_ok
end
end
Use the Ruby documentation convention: . (or ::) for class methods, # for instance methods.
# bad
describe 'the authenticate method for User'
describe 'if the user is an admin'
# good
describe '.authenticate'
describe '#admin?'
Group with context; full example names (all block descriptions concatenated) should read as a sentence.
# bad
it 'has 200 status code if logged in' do
expect(response).to respond_with 200
end
# good
context 'when logged in' do
it { is_expected.to respond_with 200 }
end
context 'when logged out' do
it { is_expected.to respond_with 401 }
end
subject when several examples relate to the same object under test.subject(:article) { ... } and expect(article).to .... Use anonymous subject only when you use is_expected and never reference the subject by name.guest_article) so intent is clear.# good – named subject
describe Article do
subject(:article) { FactoryBot.create(:article) }
it 'is not published on creation' do
expect(article).not_to be_published
end
end
# good – anonymous when using is_expected
context 'when not valid' do
it { is_expected.to respond_with 422 }
end
:aggregate_failures when you have several.context and keep the example description about the outcome. Keep descriptions under ~60 characters; use context to split.# bad
it 'should return the summary'
it 'returns the summary if it is present'
# good
context 'when display name is present' do
it 'returns the display name' do
# ...
end
end
it 'returns the summary'
it 'does not change timings'
Use expect only; never should. For one-liners with implicit subject, use is_expected.to.
# bad
response.should respond_with_content_type(:json)
it { should respond_with 422 }
# good
expect(response).to respond_with_content_type(:json)
it { is_expected.to respond_with 422 }
Configure RSpec to enforce expect syntax:
# spec_helper.rb or rails_helper.rb
RSpec.configure do |config|
config.expect_with :rspec do |c|
c.syntax = :expect
end
end
Prefer let over before { @var = ... }. Use let! when the value must exist before the example (e.g. testing scopes or queries). Don't overuse let for trivial primitives; balance reuse vs. clarity.
# bad
before { @resource = FactoryBot.create(:device) }
# good
let(:resource) { FactoryBot.create(:device) }
let!(:user) { FactoryBot.create(:user) } # when you need it loaded before the example
expect(article).to be_published instead of expect(article.published?).to be true.include, eq) instead of hand-rolled expectations.be: Don't use expect(x).to be; use be_truthy, be_nil, or a specific matcher (e.g. be_an(Author)).any_instance_of: Avoid allow_any_instance_of / expect_any_instance_of; stub or inject the dependency instead.expect { do_something }.to change(something).to(new_value) over implicit subject with a lambda.# bad
expect(article.published?).to be true
expect(article.author).to be
# good
expect(article).to be_published
expect(article.author).to be_truthy
expect(article.author).to be_an(Author)
instance_double, object_double, class_double, and verifying partial doubles over non-verifying doubles. Keep verify_partial_doubles enabled.stub_const or anonymous Class.new and assign to a let.ActiveSupport::Testing::TimeHelpers#freeze_time) instead of stubbing Time.now / Date.change(Article, :count).by(1) or similar so the example is self-contained..method or #method; context with when/with/withoutdevelopment
Ruby Style Guide (rubystyle.guide) conventions. Use when writing, formatting, or reviewing Ruby code for layout, naming, flow of control, methods, classes, and idioms. Complements RuboCop.
development
Ruby-focused. Transforms junior-level code into senior-engineer quality software through SOLID, TDD, and clean code. Examples and references use Ruby/RSpec. Use when writing or refactoring Ruby code, planning architecture, reviewing code, or creating tests.
development
Ruby skills bundle. Contains Ruby-oriented SOLID, TDD, clean code, Ruby Style Guide, and RSpec/Better Specs. Use when working with Ruby code.
documentation
Fetch GitHub issues, spawn sub-agents to implement fixes and open PRs, then monitor and address PR review comments. Usage: /gh-issues [owner/repo] [--label bug] [--limit 5] [--milestone v1.0] [--assignee @me] [--fork user/repo] [--watch] [--interval 5] [--reviews-only] [--cron] [--dry-run] [--model glm-5] [--notify-channel -1002381931352]