How to test your Rails app
RSpec
RSpec is a testing tool for Ruby, created for behavior-driven development (BDD). It is the most frequently used testing library for Ruby in production applications. Even though it has a very rich and powerful DSL (domain-specific language), at its core it is a simple tool which you can start using rather quickly.
Apart from the Rspec gem we will use the following tools:
Database Cleaner
Before each test case we need to make sure that our database is clean. If we leave information on the database, this information can cause unwanted failures.
FactoryBot
To test our platform we need data. There are two ways to create data for our tests without creating everything manually: Fixtures and Factories (Please look up the difference). At eagerworks we use factories to create our test data.
Faker
We have factories but adding emails, names, addresses to our factories can be a pain in the ass. That is why we use faker
gem to make it easier.
Shoulda Matchers
Shoulda Matchers provides one-liners to test common Rails functionality. We will use Shoulda Matchers to test model associations and validations.
Capybara
Capybara helps us test web applications by simulating how a real user would interact with your app. This tool will provide a test server for us to use on our tests.
Selenium
By default, Capybara uses the :rack_test
driver, which is fast but limited: it does not support JavaScript, nor it is able to access HTTP resources outside of your Rack application, such as remote APIs and OAuth services. To get around these limitations we will use Selenium driver.
Simplecov
SimpleCov is a code coverage analysis tool for Ruby. We will use this tool to make sure that most of our code is being tested.
Step by Step
1) Create your factories
To start testing our Rails app we need data. We need to create factories for each model that we have on our Rails project.
spec/factories/user.rb
FactoryBot.define do
factory :user do
client
name { Faker::Name.name }
email { Faker::Internet.email }
phone_number { '099999999' }
password { Faker::Internet.password }
validated { true }
end
end
2) Test your models
All the logic of our Rails app uses the defined models. We need to make sure that our models work as expected before testing anything else. When testing a model it's very important to check that the factory that we created for that model is valid. The next step is to test the model validations and associations. Finally we need to implement unit tests for each of the model's method.
require 'rails_helper'
RSpec.describe User, type: :model do
it 'has a valid factory' do
expect(build(:user)).to be_valid
end
describe 'associations' do
it { is_expected.to have_many :purchases }
end
describe 'validations' do
it { is_expected.to validate_presence_of(:first_name) }
it { is_expected.to validate_presence_of(:last_name) }
it { is_expected.to validate_presence_of(:phone_number) }
it { is_expected.to validate_presence_of(:email) }
end
describe '#method' do
end
end
3) Test your services
Implement unit tests for your services.
4) Feature tests
Feature specs are high-level tests meant to exercise slices of functionality through an application. They should drive the application only via its external interface, usually web pages.
Feature specs don't have to pay too much attention to HTML structure. They need to validate that your app features are working as expected.
For example, let's test the login feature:
require 'rails_helper'
RSpec.feature 'user login', type: :feature do
let!(:user) { create(:user, password: 'specspec') }
context 'with valid credentials' do
it 'redirects logged in user to categories index' do
visit '/users/sign_in'
fill_in 'user_email', with: user.email
fill_in 'user_password', with: user.password
click_button 'Log in'
expect(page).to have_current_path(categories_path)
end
end
context 'with invalid credentials' do
xit 'shows login error'
end
end
end