Ror Testing
title: Ruby on Rails Testing — Complete Guide to RSpec & Minitest description: 'Learn Ruby on Rails testing: RSpec setup, model specs, controller specs, request specs, factories, feature specs with Capybara, and test-driven development.' date: 2026-06-28 lastmod: 2026-06-28 weight: 26 tags: [backend, ror]
Rails testing uses RSpec or Minitest to verify application behavior through model specs, request specs, system specs, and integration tests with FactoryBot and Capybara.
## What You'll Learn
By the end of this tutorial, you'll set up RSpec, write model and request specs, use FactoryBot for test data, implement system specs with Capybara, and follow TDD practices.
## Real-World Use
A Rails app has 1000+ RSpec tests running in CI. Every pull request runs the full suite in 3 minutes. A red build blocks merging. Tests cover models, requests, and critical user flows.
## Testing Learning Path
```mermaid
flowchart LR
A[API] --> B[Testing]
B --> C[Asset Pipeline]
C --> D[Mailers]
D --> E[Background Jobs]
B --> F{You Are Here}
style F fill:#f90,color:#fff
RSpec Setup
# Gemfile
group :development, :test do
gem "rspec-rails"
gem "factory_bot_rails"
gem "faker"
end
group :test do
gem "capybara"
gem "selenium-webdriver"
gem "shoulda-matchers"
end
bundle install
rails generate rspec:install
# Creates spec/spec_helper.rb and spec/rails_helper.rb
Model Specs
# spec/models/post_spec.rb
require "rails_helper"
RSpec.describe Post, type: :model do
describe "validations" do
it { should validate_presence_of(:title) }
it { should validate_length_of(:title).is_at_least(5) }
it { should validate_presence_of(:body) }
end
describe "associations" do
it { should belong_to(:user) }
it { should have_many(:comments).dependent(:destroy) }
end
describe "scopes" do
let!(:published_post) { create(:post, published: true) }
let!(:draft_post) { create(:post, published: false) }
it "returns only published posts" do
expect(Post.published).to include(published_post)
expect(Post.published).not_to include(draft_post)
end
end
end
FactoryBot
# spec/factories/posts.rb
FactoryBot.define do
factory :post do
title { Faker::Book.title }
body { Faker::Lorem.paragraphs(number: 3).join("\n\n") }
published { true }
user
end
end
# spec/factories/users.rb
FactoryBot.define do
factory :user do
email { Faker::Internet.email }
password { "password123" }
username { Faker::Internet.username }
end
end
Request Specs
# spec/requests/posts_spec.rb
require "rails_helper"
RSpec.describe "Posts", type: :request do
let(:user) { create(:user) }
let(:post_record) { create(:post, user: user) }
describe "GET /posts" do
it "returns a successful response" do
get posts_path
expect(response).to have_http_status(:success)
end
end
describe "POST /posts" do
context "when authenticated" do
before { sign_in user }
it "creates a new post" do
expect {
post posts_path, params: { post: attributes_for(:post) }
}.to change(Post, :count).by(1)
expect(response).to redirect_to(post_path(Post.last))
end
end
context "when not authenticated" do
it "redirects to login" do
post posts_path, params: { post: attributes_for(:post) }
expect(response).to redirect_to(new_user_session_path)
end
end
end
describe "DELETE /posts/:id" do
it "destroys the post" do
post_record # Create the record
expect {
delete post_path(post_record)
}.to change(Post, :count).by(-1)
end
end
end
System Specs (Capybara)
# spec/system/user_registration_spec.rb
require "rails_helper"
RSpec.describe "User Registration", type: :system do
it "allows a user to sign up" do
visit new_user_registration_path
fill_in "Email", with: "test@example.com"
fill_in "Password", with: "password123"
fill_in "Password confirmation", with: "password123"
click_button "Sign up"
expect(page).to have_content("Welcome! You have signed up successfully.")
end
end
Common Mistakes
1. Testing Implementation Details
Test behavior (what it does), not implementation (how it does it). Avoid testing private methods.
2. Slow Tests
Slow tests discourage running. Use let! over before(:each) carefully. Avoid unnecessary database hits.
3. Not Using Factories
Fixtures are hard to maintain. FactoryBot creates test data flexibly with traits and associations.
4. Skipping Request Specs
Request specs test the full HTTP stack (routing, auth, controllers). More valuable than controller specs.
5. Not Running Tests in CI
CI should run the full test suite on every push. A failing test should block deployment.
Practice Questions
1. What is RSpec?
A behavior-driven development (BDD) testing framework for Ruby. The most popular Rails test framework.
2. What is FactoryBot?
A gem for defining test data factories. Creates model instances with default attributes and associations.
3. What is the difference between model and request specs?
Model specs test model logic (validations, scopes). Request specs test full HTTP endpoints (controllers, auth, responses).
4. What are Capybara system specs?
System specs test user interactions in a browser (clicking, filling forms, navigating pages).
5. Challenge: Write a complete test suite for a Post model with validations, associations, and request specs.
# Model spec
RSpec.describe Post, type: :model do
it { should validate_presence_of(:title) }
it { should belong_to(:user) }
end
# Request spec
RSpec.describe "Posts", type: :request do
it "lists posts" do
get posts_path
expect(response).to have_http_status(:ok)
end
end
FAQ
Mini Project: Test Suite
Write model, request, and system specs for a Rails blog app.
rails generate rspec:install
# spec/models/post_spec.rb - Write model specs
# spec/requests/posts_spec.rb - Write request specs
# spec/system/posts_spec.rb - Write system specs
bundle exec rspec
What's Next
Ruby on Rails Asset Pipeline Ruby on Rails Mailers
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro