[Ruby on Rails] Model test with RSpec

Development environment

ruby 2.5.7 Rails 5.2.4.3 OS: macOS Catalina

Premise

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

model test preparation

・ Validation settings

This time we will test if there is a title column and the number of characters.

app/models/post.rb


class Post < ApplicationRecord
  belongs_to :user
  validates :title, presence: true, length: {maximum: 20}
end

・ Creating a file

① Create models folder and factories folder under spec, Also create a file for the model you want to test. This time we will test the post model. Also, to ensure that users can only post while logged in, Also create a use model. The file structure is as follows.   spec/models/post_spec.rb → Describe what you want to test

spec/factories/post.rb spec/factories/user.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

...

Actual code

First, create dummy data.

spec/factories/user.rb


FactoryBot.define do
  factory :user 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) }
    user
  end
end

Next, write the test code.

spec/models/post_spec.rb


require 'rails_helper'

RSpec.describe 'Post model testing', type: :model do
  describe 'Validation test' do
    #Use the dummy data created by factories.
    let(:user) { FactoryBot.create(:user) }
    let!(:post) { build(:post, user_id: user.id) }

    # test_Create a post and check if you can register in the blank.
    subject { test_post.valid? }
    let(:test_post) { post }


    context 'title column' do
      it 'Must not be blank' do
        test_post.title = ''
        is_expected.to eq false;
      end
      it 'Must be 20 characters or less' do
        post.title = Faker::Lorem.characters(number:21)
        expect(post.valid?).to eq false;
      end
    end
  end
  describe 'Testing the association' do
    context 'Relationship with customer model' do
      it 'N:Is 1' do
        expect(Post.reflect_on_association(:user).macro).to eq :belongs_to
      end
    end

    # has_It is also described by many relationships.
    # context 'Relationship with PostComment model' do
      # it '1:Is N' do
        # expect(Post.reflect_on_association(:post_comments).macro).to eq :has_many
      # end
    # end
  end
end

Then do the following in your terminal:

$ rspec spec/models

If you pass the test

Finished in 0.52408 seconds (files took 2.11 seconds to load)
3 examples, 0 failures

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

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, Validation to prevent registration with blank presence: true 2, Validation of character limit length: {maximum: 20} 3, Confirmation of relationship relationships belongs_to: user

I tested the above, but there are many other testing methods, so If you are interested, please check it out.

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

[Ruby on Rails] Model test with RSpec
[Ruby on Rails] View test with RSpec
[Ruby on Rails] Controller test with RSpec
[Rails] Test with RSpec
Introducing Rspec with Ruby on Rails x Docker
Understand code coverage with Rspec, the Ruby on Rails test framework
Introducing Rspec, a Ruby on Rails test framework
Run Ruby on Rails RSpec tests with GitHub Actions
Let's unit test with [rails] Rspec!
[Ruby on Rails] 1 model CRUD (Routing Main)
[Ruby on Rails] model, controller terminal command
Notes on using FCM with Ruby on Rails
Test run on rails
Testing model with RSpec
Ruby on Rails Elementary
Ruby on Rails basics
Test Nokogiri with Rspec.
Ruby On Rails Association
I rewrote the Rails tutorial test with RSpec
[Ruby on Rails] Until the introduction of RSpec
Publish the app made with ruby on rails
[Rails] Procedure for linking databases with Ruby On Rails
Determine the current page with Ruby on Rails
[Ruby on Rails] Upload multiple images with refile
I made a portfolio with Ruby On Rails
[Rails] From test preparation to model unit testing [RSpec]
[Ruby on Rails Tutorial] Error in the test in Chapter 3
Portfolio creation Ruby on Rails
Ruby on rails learning record -2020.10.04
[Ruby on Rails] Delete s3 images with Active Strage
[Ruby on Rails] Debug (binding.pry)
Ruby on rails learning record -2020.10.05
[Rails / RSpec] Write Model test (using Shoulda Matchers / FactoryBot)
Ruby on Rails basic learning ①
Test Active Strage with RSpec
[Ruby on Rails] about has_secure_password
Ruby on rails learning record-2020.10.07 ②
[Ruby On Rails] Error in test using RSpec MySQL client is not connected
Commentary on partial! --Ruby on Rails
Test GraphQL resolver with rspec
Ruby on rails learning record-2020.10.07 ①
Cancel Ruby on Rails migration
[Rails] About Rspec response test
Ruby on rails learning record -2020.10.06
Ruby on Rails validation summary
[Ruby on Rails] Search function (model, method selection formula)
Created RSS / Atom format sitemap with Ruby on Rails
Ruby on Rails Basic Memorandum
I tried installing Ruby on Rails related plugin with vim-plug
[Ruby on Rails] Add a column with a foreign key constraint
[Ruby on Rails] Elimination of Fat Controller-First, logic to model-
[Ruby on Rails] Implement login function by add_token_to_users with API
[Apple login] Sign in with Apple implementation procedure (Ruby on Rails)
[Ruby On Rails] When a model unit test is performed with RSpec using FactoryBot, an error occurs because the foreign key is not entered.
Install Ruby on MSYS2 with pacman
Ruby on Rails Overview (Beginner Summary)
[Ruby on Rails] Read try (: [],: key)
Installing Ruby + Rails on Ubuntu 18.04 (rbenv)
[Ruby on Rails] Introduced paging function
Basic knowledge of Ruby on Rails
Progate Ruby on Rails5 Looking Back