[Ruby on Rails] Controller test with RSpec

Development environment

ruby 2.5.7 Rails 5.2.4.3 OS: macOS Catalina

Premise

We will proceed on the premise that this is done. [Ruby on Rails] Until RSpec is introduced

Click here to test the model [Ruby on Rails] Model test with RSpec

Controller test preparation

・ Creating an action

This time only when the user logs in Test if it is displayed.

app/controllers/posts_controller.rb


class Admins::PostsController < ApplicationController
  before_action :authenticate_user!
  def index
    @posts = Post.all
  end
end
Supplement [before_action: authenticate_user!] A helper method for gem devise.

・ Creating a file

① Create requests folder and factories folder under spec. In the requests folder, also create a file for the controller you want to test, Create a model of dummy data in the factories folder.

This time to test the post controller The file structure is as follows.

spec/requests/posts_request_spec.rb
→ Describe the content you want to test.

spec/factories/post.rb
spec/factories/admin.rb
→ Create dummy data.

② Enables Factory Bot. It is convenient to use it because you can register the DB and build the model like user = create (: user). Create a support folder and factory_bot.rb file under spec and describe as follows.

spec/support/factory_bot.rb


RSpec.configure do |config|
  config.include FactoryBot::Syntax::Methods
end

Then add the following:

spec/rails_helper.rb


# This file is copied to spec/ when you run 'rails generate rspec:install'
require 'spec_helper'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../config/environment', __dir__)
# Prevent database truncation if the environment is production
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'rspec/rails'
require 'support/factory_bot' #<-Addition

...

Edit rails_helper.rb

The following contentsRSpec.configure do |config|Add in.

  • With this description, the sign_in method can be used.

spec/rails_helper.rb


RSpec.configure do |config|

...

  config.include Devise::Test::IntegrationHelpers, type: :request # <--add to
end

Actual code

First, create dummy data.

spec/factories/admin.rb


FactoryBot.define do
  factory :admin do
    email { Faker::Internet.email }
    phone_number { 12345678909 }
    password { 'password' }
    password_confirmation { 'password' }
  end
end

spec/factories/post.rb


FactoryBot.define do
  factory :post do
    body { Faker::Lorem.characters(number:20) }
    admin
  end
end

Next, write the test code.

spec/requests/posts_request_spec.rb


require 'rails_helper'

RSpec.describe "post controller test", type: :request do
  let(:admin) { create(:admin) }
  let(:post) { create(:post) }
  describe 'Logind' do
    before do
      sign_in admin
    end
    context "Post list page is displayed correctly" do
      before do
        get admins_posts_path
      end
      it 'Request should be 200 OK' do
        expect(response.status).to eq 200
      end
      it 'The title is displayed correctly' do
        expect(response.body).to include("Post list")
      end
    end
  end
  describe 'Non-login' do
    context "Does not transition to the post list page" do
      before do
        get admins_posts_path(admin)
      end
      it 'Request should be 401 OK' do
        expect(response.status).to eq 401
      end
    end
  end


  # get admins_posts_path(admin)If so, it is a 401 error because the password is different,
  # get admins_posts_If it is path, it will be 302 redirect, so please describe it by the person you want to test.

  # describe 'Non-login' do
  #   context "Does not transition to the post list page" do
  #     before do
  #       get admins_posts_path
  #     end
  #     it 'Request should be 302 OK' do
  #       expect(response.status).to eq 302
  #     end
  #   end
  # end
end

Then do the following in your terminal:

Terminal


$ rspec spec/requests

If you pass the test

Finished in 3.64 seconds (files took 2.75 seconds to load)
3 examples, 0 failures

Since it is displayed like this, it means that the test content is correct.

Reference (excerpt from model test)

[Ruby on Rails] Model test with RSpec On the contrary, if it does not pass the test, you can see where the error is occurring in this way, so You will be able to see if the test code is wrong, the validation is wrong, and so on.

Failures:

  1)Post model test Validation test title column Must be 20 characters or less
     Failure/Error: let!(:post) { build(:post) }

     NoMethodError:
       undefined method `build' for #<RSpec::ExampleGroups::Post::Nested::Title:0x000000000619e938>
     # ./spec/models/post_spec.rb:9:in `block (3 levels) in <top (required)>'

  2)Post model test Validation test title column Must not be blank
     Failure/Error: let!(:post) { build(:post) }

     NoMethodError:
       undefined method `build' for #<RSpec::ExampleGroups::Post::Nested::Title:0x0000000007491518>
     # ./spec/models/post_spec.rb:9:in `block (3 levels) in <top (required)>'
Finished in 0.07992 seconds (files took 2.41 seconds to load)
2 examples, 2 failures

Failed examples:

rspec ./spec/models/post_spec.rb:11 #Post model test Validation test title column Must be 20 characters or less
rspec ./spec/models/post_spec.rb:15 #Post model test Validation test title column Must not be blank

Also, using rspec ./spec/models/post_spec.rb:11 at the bottom, You can also check the test contents individually as shown below.

Terminal


$ rspec spec/models/post_spec.rb:11

Summary

This time 1, Is the post list screen displayed correctly while logged in? 2, Is the title displayed correctly while logged in? 3, If you are not logged in, can you browse?

I tested these 3 points.

Folder name requests It is requested to test whether it is responding correctly to the request. Therefore, if the request is different, it will return an error of 401 or 302, so Please describe according to the error you want to display.

Also, on twitter, technologies and ideas that have not been uploaded to Qiita are also uploaded, so I would be grateful if you could follow me. Click here for details https://twitter.com/japwork

Recommended Posts