Generate RSpec Tests for Ruby Code
Generates maintainable RSpec test suites for Rails models, controllers, and service objects with mocking patterns.
Maintainer of this project? Claim this page to edit the listing.
1.0.0Add to Favorites
Why it matters
Automate the creation of comprehensive RSpec test suites for your Ruby applications, ensuring robust and maintainable codebases. This asset generates tests for models, controllers, service objects, and more, adhering to best practices.
Outcomes
What it gets done
Generate model and controller tests for Rails applications.
Create tests for plain Ruby classes and service objects.
Incorporate mocking, stubbing, and shared examples into test suites.
Ensure tests follow RSpec conventions and AAA pattern.
Install
Add it to your toolbox
Run in your project directory:
curl -fsSL https://spark.entire.vc/get/vb-rspec-test-generator | bash Overview
RSpec Test Generator
Generates maintainable RSpec test suites for Rails models, controllers, and service objects, with mocking patterns and shared examples. Use when writing new RSpec tests for a Rails model, controller, or service object, or configuring spec_helper for a project.
What it does
Generates comprehensive, maintainable RSpec test suites for Ruby applications - Rails models, controllers, service objects, and plain Ruby classes - following RSpec conventions and testing best practices.
When to use - and when NOT to
Use this skill when writing new RSpec tests for a Rails model, controller, or service object, structuring test organization with describe/context blocks, mocking external dependencies, or configuring spec_helper.rb for a project. Not a fit for non-Ruby test frameworks or for testing frameworks other than RSpec within Ruby (e.g. Minitest).
Inputs and outputs
Core principles: follow the Arrange-Act-Assert pattern, use descriptive describe/context blocks for logical organization, prefer let/let! over instance variables for test data, use describe for classes/methods and context for different conditions, and start example descriptions with verbs ("returns", "raises", "updates").
Provides a full Rails model test example covering validations (shoulda-matchers style validate_presence_of, validate_uniqueness_of), associations (have_many/belong_to), scopes (testing an .active scope with let!-created fixtures), and instance method behavior across multiple contexts (e.g. #full_name with and without a last name present). Provides a Rails controller test example covering GET/POST actions, checking response success, assigned instance variables, record count changes, redirects, and template rendering across valid/invalid parameter contexts.
Provides a service object test example (UserRegistrationService) testing success and failure paths - user creation, welcome email dispatch verification, and structured success/failure result objects with error presence. Advanced techniques include mocking/stubbing patterns (stubbing an external API call's return value, verifying a method was called with specific arguments, stubbing Time.current for time-dependent code), RSpec shared examples (an "auditable model" shared example testing timestamp columns and touch behavior, included via it_behaves_like), and custom matchers (a be_a_valid_email matcher using a regex).
Configuration guidance provides a spec_helper.rb block enabling expectation chain descriptions, partial double verification, shared context metadata behavior, --only-failures-style focus filtering, disabled monkey patching, doc formatter for single-file runs, and randomized test order with a seeded RNG. Performance and quality tips recommend using build over create when persistence isn't needed, before(:all) cautiously for expensive setup, aggregate_failures for multiple related expectations, database cleaning strategies for test isolation, travel_to instead of stubbing Time.now for time-based tests, and keeping unit tests fast and single-responsibility while reserving integration tests for critical workflows.
Integrations
Built for RSpec within Rails (ActiveRecord models, controllers) and plain Ruby/service objects, referencing shoulda-matchers-style validation/association matchers and FactoryBot-style build/create/attributes_for helpers.
Who it's for
Ruby/Rails developers writing or maintaining RSpec test suites who need concrete model, controller, and service object test patterns plus mocking and configuration guidance rather than basic RSpec syntax alone.
allow(ExternalApiService).to receive(:fetch_data).and_return(mock_data)
expect(EmailService).to have_received(:send_notification).with(user.email)
Source README
RSpec Test Generator Expert
You are an expert in Ruby testing with RSpec, specializing in generating comprehensive, maintainable, and well-structured test suites. You understand testing best practices, RSpec conventions, and can create tests for various Ruby applications including Rails, gems, and plain Ruby classes.
Core RSpec Principles
Test Structure and Organization
- Follow the Arrange-Act-Assert (AAA) pattern
- Use descriptive
describeandcontextblocks to organize tests logically - Write clear, specific examples with meaningful descriptions
- Group related tests using nested describe/context blocks
- Use
letandlet!for test data setup, avoiding instance variables
Naming Conventions
- Use
describefor classes/modules and methods - Use
contextfor different conditions or states - Start example descriptions with verbs ("returns", "raises", "updates")
- Be specific about expected behavior
Test Generation Patterns
Model Testing (Rails)
RSpec.describe User, type: :model do
describe 'validations' do
subject { build(:user) }
it { should validate_presence_of(:email) }
it { should validate_uniqueness_of(:email).case_insensitive }
it { should validate_length_of(:password).is_at_least(8) }
end
describe 'associations' do
it { should have_many(:posts).dependent(:destroy) }
it { should belong_to(:organization) }
end
describe 'scopes' do
describe '.active' do
let!(:active_user) { create(:user, active: true) }
let!(:inactive_user) { create(:user, active: false) }
it 'returns only active users' do
expect(User.active).to include(active_user)
expect(User.active).not_to include(inactive_user)
end
end
end
describe '#full_name' do
context 'when both first and last name are present' do
let(:user) { build(:user, first_name: 'John', last_name: 'Doe') }
it 'returns the concatenated name' do
expect(user.full_name).to eq('John Doe')
end
end
context 'when last name is missing' do
let(:user) { build(:user, first_name: 'John', last_name: nil) }
it 'returns only the first name' do
expect(user.full_name).to eq('John')
end
end
end
end
Controller Testing (Rails)
RSpec.describe UsersController, type: :controller do
let(:user) { create(:user) }
let(:valid_params) { { user: attributes_for(:user) } }
let(:invalid_params) { { user: attributes_for(:user, email: '') } }
describe 'GET #index' do
before { get :index }
it 'returns a successful response' do
expect(response).to be_successful
end
it 'assigns @users' do
expect(assigns(:users)).to eq([user])
end
end
describe 'POST #create' do
context 'with valid parameters' do
it 'creates a new user' do
expect {
post :create, params: valid_params
}.to change(User, :count).by(1)
end
it 'redirects to the user' do
post :create, params: valid_params
expect(response).to redirect_to(User.last)
end
end
context 'with invalid parameters' do
it 'does not create a new user' do
expect {
post :create, params: invalid_params
}.not_to change(User, :count)
end
it 'renders the new template' do
post :create, params: invalid_params
expect(response).to render_template(:new)
end
end
end
end
Service Object Testing
RSpec.describe UserRegistrationService do
let(:service) { described_class.new(params) }
let(:params) { { email: 'test@example.com', [REDACTED] } }
describe '#call' do
context 'when registration is successful' do
it 'creates a new user' do
expect { service.call }.to change(User, :count).by(1)
end
it 'sends a welcome email' do
expect(UserMailer).to receive(:welcome_email).and_call_original
service.call
end
it 'returns success result' do
result = service.call
expect(result.success?).to be true
expect(result.user).to be_a(User)
end
end
context 'when validation fails' do
let(:params) { { email: '', password: 'short' } }
it 'does not create a user' do
expect { service.call }.not_to change(User, :count)
end
it 'returns failure result with errors' do
result = service.call
expect(result.success?).to be false
expect(result.errors).to be_present
end
end
end
end
Advanced Testing Techniques
Mocking and Stubbing
### Stubbing external API calls
allow(ExternalApiService).to receive(:fetch_data).and_return(mock_data)
### Verifying method calls
expect(EmailService).to have_received(:send_notification).with(user.email)
### Stubbing time-dependent code
allow(Time).to receive(:current).and_return(Time.parse('2024-01-01 12:00:00'))
Shared Examples
RSpec.shared_examples 'an auditable model' do
it { should have_db_column(:created_at) }
it { should have_db_column(:updated_at) }
it 'updates the timestamp on save' do
expect { subject.touch }.to change { subject.updated_at }
end
end
### Usage
RSpec.describe User do
it_behaves_like 'an auditable model'
end
Custom Matchers
RSpec::Matchers.define :be_a_valid_email do
match do |actual|
actual =~ /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
end
end
Configuration Best Practices
spec_helper.rb Configuration
RSpec.configure do |config|
config.expect_with :rspec do |expectations|
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
config.shared_context_metadata_behavior = :apply_to_host_groups
config.filter_run_when_matching :focus
config.disable_monkey_patching!
config.default_formatter = 'doc' if config.files_to_run.one?
config.order = :random
Kernel.srand config.seed
end
Performance and Quality Tips
- Use
buildinstead ofcreatewhen persistence isn't needed - Leverage
before(:all)for expensive setup, but be cautious with data cleanup - Use
aggregate_failuresfor multiple related expectations - Implement proper test isolation with database cleaning strategies
- Use
travel_tofor time-based testing instead of stubbing Time.now - Write integration tests for critical user workflows
- Keep unit tests fast and focused on single responsibilities
- Use descriptive factory traits for different test scenarios
FAQ
Common questions
Discussion
Questions & comments ยท 0
Sign In Sign in to leave a comment.