Testing Rails Applications: From RSpec to System Tests
2 min read

Complete Rails Testing Guide
Testing is crucial for maintaining a healthy Rails application. Let's explore modern testing practices using RSpec and system tests.
Setting Up RSpec
# Gemfile
group :development, :test do
gem 'rspec-rails'
gem 'factory_bot_rails'
gem 'faker'
gem 'shoulda-matchers'
end
group :test do
gem 'capybara'
gem 'selenium-webdriver'
gem 'webdrivers'
end
Model Testing
# spec/models/user_spec.rb
require 'rails_helper'
RSpec.describe User, type: :model do
describe 'validations' do
it { should validate_presence_of(:email) }
it { should validate_uniqueness_of(:email) }
it { should have_secure_password }
end
describe 'associations' do
it { should have_many(:posts).dependent(:destroy) }
it { should have_many(:comments) }
end
describe '#full_name' do
it 'returns the combined first and last name' do
user = User.new(first_name: 'John', last_name: 'Doe')
expect(user.full_name).to eq('John Doe')
end
end
end
Controller Testing
# spec/controllers/posts_controller_spec.rb
RSpec.describe PostsController, type: :controller do
let(:user) { create(:user) }
let(:post_obj) { create(:post, user: user) }
before { sign_in user }
describe 'GET #index' do
it 'returns successful response' do
get :index
expect(response).to be_successful
end
end
describe 'POST #create' do
context 'with valid params' do
it 'creates a new post' do
expect {
post :create, params: { post: attributes_for(:post) }
}.to change(Post, :count).by(1)
end
end
end
end
System Tests with Capybara
# spec/system/user_creates_post_spec.rb
require 'rails_helper'
RSpec.describe 'User creates a post', type: :system do
let(:user) { create(:user) }
before do
driven_by(:selenium_chrome_headless)
sign_in user
end
it 'successfully creates a new post' do
visit new_post_path
fill_in 'Title', with: 'My New Post'
fill_in 'Content', with: 'This is the content'
select 'Published', from: 'Status'
click_button 'Create Post'
expect(page).to have_content('Post was successfully created')
expect(page).to have_content('My New Post')
end
end
Testing Best Practices
- Use factories: Create realistic test data with FactoryBot
- Keep tests focused: One assertion per test when possible
- Use contexts: Group related tests
- Mock external services: Use VCR or WebMock
- Run tests in parallel: Speed up test suite
Performance Testing
# spec/performance/posts_spec.rb
require 'rails_helper'
require 'benchmark'
RSpec.describe 'Posts performance' do
it 'loads posts index quickly' do
create_list(:post, 100)
time = Benchmark.realtime do
get posts_path
end
expect(time).to be < 0.5
end
end