Since we tested the personally developed app created as a portfolio I would like to look back on the test flow as a personal output. This time, it will be the basic content of the test related to model validation.
Testing in programming means "making sure that your program works as intended."
Ruby 2.5.1 Rails 5.2.3
User model created using gem'devise'
First, install the Gem used for testing.
--rspec-rails ▶ ︎RSpec, a gem for Rails, a language specialized for testing --factory_bot ▶ ︎ A gem that allows you to easily create a dummy instance
Gemfile
group :development, :test do
abridgement
gem 'factory_bot_rails'
gem 'rspec-rails'
end
Terminal
$ bundle install
This completes the gem installation.
First, you need to generate a file for RSpec, so execute the following command.
Terminal
$ rails g rspec:install
This will generate the following files.
Terminal
create .rspec
create spec
create spec/spec_helper.rb
create spec/rails_helper.rb
.rspec
--format documentation
Terminal
$ bundle exec rspec
I'm finally writing the test code Place the spec file where you write the test code in the directory named spec that was generated along the way. Also, since the model spec file is put together in the model directory, let's create the directory and file with a text editor.
** * The naming convention for spec files is that the spec file will be named the corresponding class name_spec.rb. ** **
This time, we will proceed on the assumption that we will perform a test related to validation of the User model, so create user_spec.rb.
First of all, we will test one by one to see if each validation at the time of new user registration is applied. This time, the validation of the User model is under the following conditions.
app/models/user.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
validates :nickname, :email, :password, :password_confirmation, presence: true
end
Test the 4 columns to which the validates presence: true is applied.
First, test the validation of the nickname with the basic description.
spec/models/user_spec.rb
require 'rails_helper'
describe User do
describe '#create' do
it "Cannot register without nickname" do
user = User.new(nickname: "", email: "[email protected]", password: "1234567", password_confirmation: "1234567")
user.valid?
expect(user.errors[:nickname]).to include("can't be blank")
end
end
end
The first line describes the file to be read for testing. The second line describes the model class. The third line describes the action name to be tested.
The grouping of it to end on the 4th to 8th lines is the test code for each one. The 4th line describes the content to be tested. The 5th line describes the creation of the instance, but it is described with a realistic assumption except that the nickname is empty. In the 6th line, if you describe the valid? Method in the created instance, you can check "whether it can not be saved by validation" when saving the instance of the class that inherits ActiveRecord :: Base. .. The 7th line describes the expected test results for the contents of the 6th line. The return value of the valid? Method is true or false, but if you use the errors method for the instance that used the valid? Method, you can check why it cannot be saved if it cannot be saved due to validation. In this case, we use the include matcher below to to predict that "an error message" can't be blank "will appear".
Zackri in Japanese "Write an expectation that the user's nickname is empty and will return the error" Cannot be empty "." It's like
Let's run the test here
Terminal
$ bundle exec rspec
1 example, 0 failures
If you see the message "0 failures for one test" as shown above, it's OK.
I will also test other validations, By using factory_bot which was introduced first, the test code of the user instance creation part can be shared, which is quite convenient.
First, let's create a directory called factories under the spec directory. Create a file called users.rb in it. ** * File naming is unified with model name plural **
Then, in an empty file, describe the common parts for creating a model instance.
spec/factories/users.rb
FactoryBot.define do
factory :user do
nickname {"Taro Tanaka"}
email {"[email protected]"}
password {"1234567"}
password_confirmation {"1234567"}
end
end
I don't have to explain anything in particular When you create an instance of the user model with the test code, it will be executed every time with the contents described.
#This is
user = User.new(nickname: "Taro Tanaka", email: "[email protected]", password: "1234567", password_confirmation: "1234567")
#This can be achieved
user = FactoryBot.build(:user)
What a further simplification of this code. There is a description to read'rails_helper'in user_spec.rb, We'll make a few tweaks to this rails_helper.rb file.
spec/rails_helper.rb
#abridgement
RSpec.configure do |config|
#Added the following description
config.include FactoryBot::Syntax::Methods
#abridgement
end
Now you are ready to go. Then ...
#This is
user = User.new(nickname: "Taro Tanaka", email: "[email protected]", password: "1234567", password_confirmation: "1234567")
#This can be achieved
user = FactoryBot.build(:user)
#Can be omitted further
user = build(:user)
The amount of code is considerably reduced ...
When I first learned this, I put values in all the columns, but can I reproduce empty columns when testing validation? There was a question ➡︎ You can do it without problems
Let's look at the rest of the test code.
spec/models/user_spec.rb
require 'rails_helper'
describe User do
describe '#create' do
it "Cannot register without nickname" do
user = build(:user, nickname: "")
user.valid?
expect(user.errors[:nickname]).to include("can't be blank")
end
it "Cannot register without email" do
user = build(:user, email: "")
user.valid?
expect(user.errors[:email]).to include("can't be blank")
end
it "Cannot register without password" do
user = build(:user, password: "")
user.valid?
expect(user.errors[:password]).to include("can't be blank")
end
it "password even if password exists_Cannot register without confirmation" do
user = build(:user, password_confirmation: "")
user.valid?
expect(user.errors[:password_confirmation]).to include("doesn't match Password")
end
it "Cannot register if password is 5 characters or less" do
user = build(:user, password: "00000", password_confirmation: "00000")
user.valid?
expect(user.errors[:password]).to include("is too short (minimum is 6 characters)")
end
#We also carry out tests when registration is possible
it "nickname and email, password and password_You can register if confirmation exists" do
user = build(:user)
expect(user).to be_valid
end
it "You can register if the password is 6 characters or more" do
user = build(:user, password: "000000", password_confirmation: "000000")
user.valid?
expect(user).to be_valid
end
end
end
The above explanation
user = build(:user)
user = build(:user, nickname: "")
By specifying the column name and value again as in the second line
You can overwrite the preset value.
In the case of this example, nickname: "Ichiro Tanaka" is overwritten with nickname: "".
By doing this, you can flexibly change the preset value (nil is also acceptable).
it "password even if password exists_Cannot register without confirmation" do
user = build(:user, password_confirmation: "")
user.valid?
expect(user.errors[:password_confirmation]).to include("doesn't match Password")
end
Also, the above include matcher part Like "can't be blank" The error message "doesn't match Password" Where are you from? I'm thinking of writing something like that If you don't know from the beginning, you can't predict the error message ...?
There was a time when I thought so ** (Note: I'm still a beginner) **
Although these error messages are originally provided by Rails Gem, Ultimately, you can still run the test
.to include("")
Then, the test execution result will be displayed in the terminal.
You expected to get the error message "", but the actual error message was "doesn't match Password"!
Will be returned.
Then Ah! Yes Yes! That's what Wai wanted to write in the test! You understand
You can also open the console to verify and confirm the flow, If you are a beginner and have a small amount of testing for personally developed apps, this method seems to be sufficient. (Looks angry)
Also, the last two tests are tests when user registration is possible. There is a be_valid matcher. This is used when you say "it will clear all validations".
Finally try running the test
Terminal
$ bundle exec rspec
7 example, 0 failures
If there are no failures for the number of tests, it's OK.
Using RSpec and FactoryBot, I looked back on a simple Rails model test.
The test I conducted this time is only a part, but I wrote the basic flow and small stories, so I hope it will help those who are new to learning.
Also, if you find any inadequacies in the contents, please let us know.
Finally, I would like to mention the Qiita article that I referred to during my study.
Thank you very much.
-[Introduction to RSpec that can be used, Part 1 "Understanding the basic syntax and useful functions of RSpec"](https://qiita.com/jnchito/items/42193d066bd61c740612#describe--it--expect-%E3% 81% AE% E5% BD% B9% E5% 89% B2% E3% 82% 92% E7% 90% 86% E8% A7% A3% E3% 81% 99% E3% 82% 8B) -[Introduction to RSpec that can be used, part 2 "Mastering frequently used matchers"](https://qiita.com/jnchito/items/2e79a1abe7cd8214caa5#%E4%BB%8A%E5%9B%9E%E8%AA% AC% E6% 98% 8E-% E3% 81% 97% E3% 81% AA% E3% 81% 84-% E5% 86% 85% E5% AE% B9)
Recommended Posts