Testing with RSpec

Episode #101 by Teacher's Avatar David Kimura

Summary

Using RSpec, learn how to create tests for your application and view your coverage.
rails test 13:04

Resources

Summary

# Terminal
rails generate rspec:install
rails g rspec:model user
rails g rspec:controller users
rails stats

# Run Tests
rspec

# Run tests of specific file and line
# where 20 is the line of spec that you want to run
rspec spec/models/user_spec.rb:20

# Gemfile
group :development, :test do
  ...
  gem 'rspec-rails'
end
gem 'simplecov', require: false, group: :test

# don't forget to add coverage to your .gitignore file

# rails_helper.rb
require 'spec_helper'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'rspec/rails'
ActiveRecord::Migration.maintain_test_schema!

RSpec.configure do |config|
  config.fixture_path = "#{::Rails.root}/spec/fixtures"
  config.use_transactional_fixtures = true
  config.infer_spec_type_from_file_location!
  config.filter_rails_from_backtrace!
end

# spec_helper.rb
require 'simplecov'
SimpleCov.start

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
end

# models/user_spec.rb
require 'rails_helper'

RSpec.describe User, type: :model do
  context 'validation tests' do
    it 'ensures first name presence' do
      user = User.new(last_name: 'Last', email: 'sample@example.com').save
      expect(user).to eq(false)
    end
    
    it 'ensures last name presence' do
      user = User.new(first_name: 'First', email: 'sample@example.com').save
      expect(user).to eq(false)
    end
    
    it 'ensures email presence' do
      user = User.new(first_name: 'First', last_name: 'Last').save
      expect(user).to eq(false)
    end
    
    it 'should save successfully' do 
      user = User.new(first_name: 'First', last_name: 'Last', email: 'sample@example.com').save
      expect(user).to eq(true)
    end
  end

  context 'scope tests' do
    let (:params) { {first_name: 'First', last_name: 'Last', email: 'sample@example.com'} }
    before(:each) do
      User.new(params).save
      User.new(params).save
      User.new(params.merge(active: true)).save
      User.new(params.merge(active: false)).save
      User.new(params.merge(active: false)).save
    end

    it 'should return active users' do
      expect(User.active_users.size).to eq(3)
    end

    it 'should return inactive users' do
      expect(User.inactive_users.size).to eq(2)
    end
  end
end

# controllers/users_controller_spec.rb
require 'rails_helper'

RSpec.describe UsersController, type: :controller do
  context 'GET #index' do
    it 'returns a success response' do
      get :index
      expect(response).to be_success # response.success?
    end
  end

  context 'GET #show' do
    it 'returns a success response' do
      user = User.create!(first_name: 'First', last_name: 'Last', email: 'first.last@example.com')
      get :show, params: { id: user.to_param }
      expect(response).to be_success
    end
  end
end