This time, we will output the method while implementing the unit test of the model for new user registration. The specifications for user registration are as follows.
Nickname required
Email address is unique
mail address is@And domain must be included
Password required
Password must be at least 7 characters
Enter the password twice, including for confirmation
User's real name is required for surname and first name
Enter the user's real name in full-width
User's real name Frigana is required for surname and first name respectively
Let the user's real name Frigana be entered in full-width
Date of birth is required
The migration file is as follows.
20200823050614_devise_create_users.rb
class DeviseCreateUsers < ActiveRecord::Migration[5.2]
def change
create_table :users do |t|
## Database authenticatable
t.string :nickname, null: false
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
t.string :family_name, null: false
t.string :family_name_kana, null: false
t.string :first_name, null: false
t.string :first_name_kana, null: false
t.date :birth_day, null: false
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
# t.integer :sign_in_count, default: 0, null: false
# t.datetime :current_sign_in_at
# t.datetime :last_sign_in_at
# t.string :current_sign_in_ip
# t.string :last_sign_in_ip
## Confirmable
# t.string :confirmation_token
# t.datetime :confirmed_at
# t.datetime :confirmation_sent_at
# t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
t.timestamps null: false
end
add_index :users, :email, unique: true
add_index :users, :reset_password_token, unique: true
# add_index :users, :confirmation_token, unique: true
# add_index :users, :unlock_token, unique: true
end
end
The model is as follows.
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
#Validation settings(Uniqueness constraint to prevent empty string from being saved)
validates :nickname, presence: true
validates :encrypted_password, presence: true
validates :family_name, presence: true
validates :family_name_kana, presence: true
validates :first_name, presence: true
validates :first_name_kana, presence: true
validates :birth_day, presence: true
#association
has_many :cards, dependent: :destroy
has_many :shipping_infos, dependent: :destroy
has_many :comments, dependent: :destroy
has_many :items
end
** ① Preparation for RSpec ** ** ② RSpec settings ** ** ③ Introduce factory_bot ** ** ④ Implementation of factory_bot ** ** ⑤ Regular expression description ** ** ⑥ Implementation of test code ** ** ⑦ Execution of test code **
First install Gem.
Gemfile.rb
group :development, :test do
#abridgement
gem 'rspec-rails'
end
group :development do
gem 'web-console'
end
# web_If console already has a description, just move the description location. Please note that if you add it, it may be duplicated.
After editing the Gemfile, don't forget to run bundle install.
Next, make basic settings for RSpec. First, create a configuration file for RSpec.
Terminal.
$ rails g rspec:install
#Success if the file is created as follows ▼
create .rspec
create spec
create spec/spec_helper.rb
create spec/rails_helper.rb
Next, add the following to .rspec
.
.rspec.
--format documentation
Next, set the directory for RSpec.
The file in which the test code by RSpec is written is called a spec file, and all spec files are stored in the spec directory generated by the rails g rspec: install
command, so create it here. Let's keep it.
Test files for models are stored under spec / models /, and test files for controllers are stored under spec / controllers /. This directory is where all the code under the app directory to be tested is located.
The spec file will be named _spec.rb with the corresponding class. This time, we will first create a spec file for "user.rb", so the name in that case will be " user_spec.rb "
.
After creating the directory, check once at this point whether ** RSpec ** can be used normally.
Terminal.
$ bundle exec rspec
#If the result is as follows, it is OK because it is operating normally.
No examples found.
Finished in 0.00031 seconds (files took 0.19956 seconds to load)
0 examples, 0 failures
Then install ** factory_bot **. Install Gem.
Gemfile.rb
group :development, :test do
#abridgement
gem 'rspec-rails'
gem 'factory_bot_rails'
end
Then run bundle install.
Next, create a directory called factories
directly under the spec directory, and create a Ruby file in it with the plural file name of the created instance. In this case, it will be ʻusers.rb`.
Edit ʻusers.rb` as follows.
users.rb
FactoryBot.define do
factory :user do
nickname {"tarou"}
email {"[email protected]"}
password {"1234567"}
encrypted_password {"1234567"}
family_name {"Yamada"}
family_name_kana {"Yamada"}
first_name {"Taro"}
first_name_kana {"Taro"}
birth_day {"2000-01-01"}
end
end
This description creates the contents according to the specifications as dummy data, so that you can easily create an instance by a specific method (build or create) in the spec file or save it in the DB. It will be like.
Next, set the regular expression in the validation according to the specifications. The required regular expressions are:
Password must be at least 7 characters
Enter the user's real name in full-width
Let the user's real name Frigana be entered in full-width
Based on these, the description in the model is as follows.
user.rb
class User < ApplicationRecord
#abridgement
validates :nickname, presence: true
validates :encrypted_password, presence: true, length: { minimum: 7 } #Here is the regular expression for the number of characters
validates :family_name, presence: true, format: {with: /\A[Ah-Hmm-One-龥]/ } #This is the user's real name full-width regular expression
validates :family_name_kana, presence: true, format: {with: /\A[A-Car-]+\z/ } #Here is the Frigana full-width regular expression
validates :first_name, presence: true, format: {with: /\A[Ah-Hmm-One-龥]/ } #This is the user's real name full-width regular expression
validates :first_name_kana, presence: true, format: {with: /\A[A-Car-]+\z/ } #Here is the Frigana full-width regular expression
#abridgement
end
Please refer to the following site for Ruby regular expressions. https://gist.github.com/nashirox/38323d5b51063ede1d41
Now it's time to implement the test code! Here are some things to keep in mind when writing test code:
(1) One value is expected in each example
② Describe the expected result clearly and clearly
③ Test both what you want to happen and what you don't want to happen
④ Make it DRY moderately while considering readability
Write the following code in user_spec.rb.
user_spec.rb
require 'rails_helper'
describe User do
describe '#create' do
end
end
Since this is a unit test of the User model, it will be describe User do
, and since a new user will be created, it will be describe'# create' do
, and the test code will be written in the describ on the second line.
First, test that ** can be registered if all items are entered **. The code and its explanation are as follows.
user_spec.rb
require 'rails_helper'
describe User do
describe '#create' do
#Test when entered ▼
it "Registration is possible if all items are entered" do #What you want to test
user = build(:user) #Using the build method on the variable user, factory_Substitute bot dummy data
expect(user).to be_valid #Execute a test to see if registration is done with the information of the variable user
end
end
end
The next test is as follows.
Cannot register without nickname
Cannot register without email
Cannot register without password
encrypted_Cannot register without password
family_Cannot register without name
family_name_Cannot register without kana
first_Cannot register without name
first_name_Cannot register without kana
birth_Cannot register if there is no day
These conditions are for testing the required items (null: false, presence: true) in the specification. Let's describe it. The explanation will be given in the test part of ** Cannot be registered without nickname **.
user.spec.rb
require 'rails_helper'
describe User do
describe '#create' do
#Test when entered ▼
it "Registration is possible if all items are entered" do
user = build(:user)
expect(user).to be_valid
end
# nul:false, presence:True test ▼
it "Cannot register without nickname" do #What you want to test
user = build(:user, nickname: nil) #Using the build method on the variable user, factory_Substitute bot dummy data(In this case, intentionally set the value of nickname to)
user.valid? #Test "Is it in a state where it cannot be saved by validation" using the validation method?
expect(user.errors[:nickname]).to include("Please enter") #Use the errors method to check "Why can't I save if validation doesn't work?".to include("Please enter")Write the error statement in(Since Rails is translated into Japanese, the error text is also in Japanese.)
end
it "Cannot register without email" do
user = build(:user, email: nil)
user.valid?
expect(user.errors[:email]).to include("Please enter")
end
it "Cannot register without password" do
user = build(:user, password: nil)
user.valid?
expect(user.errors[:password]).to include("Please enter")
end
it "encrypted_Cannot register without password" do
user = build(:user, encrypted_password: nil)
user.valid?
expect(user.errors[:encrypted_password]).to include("Please enter")
end
it "family_Cannot register without name" do
user = build(:user, family_name: nil)
user.valid?
expect(user.errors[:family_name]).to include("Please enter")
end
it "family_name_Cannot register without kana" do
user = build(:user, family_name_kana: nil)
user.valid?
expect(user.errors[:family_name_kana]).to include("Please enter")
end
it "first_Cannot register without name" do
user = build(:user, first_name: nil)
user.valid?
expect(user.errors[:first_name]).to include("Please enter")
end
it "first_name_Cannot register without kana" do
user = build(:user, first_name_kana: nil)
user.valid?
expect(user.errors[:first_name_kana]).to include("Please enter")
end
it "birth_Cannot register if there is no day" do
user = build(:user, birth_day: nil)
user.valid?
expect(user.errors[:birth_day]).to include("Please enter")
end
end
end
Next, we will test the uniqueness constraint of email.
user.spec.rb
require 'rails_helper'
describe User do
describe '#create' do
#abridgement
#Email uniqueness constraint test ▼
it "Cannot register if there are duplicate emails" do
user = create(:user) #Factory to variable user and database using create method_Save bot dummy data
another_user = build(:user, email: user.email) #Second another_Create user as a variable and use build method to intentionally duplicate email content
another_user.valid? # another_Test user's "Cannot save due to validation"
expect(another_user.errors[:email]).to include("Already exists") #Use the errors method to check the email "Why can't I save due to validation?" And write the error statement that caused it.
end
end
end
Next, run a test that cannot be registered without a confirmation password.
user.spec.rb
require 'rails_helper'
describe User do
describe '#create' do
#abridgement
#Test that requires confirmation password ▼
it "encrypted even if password exists_Cannot register without password" do
user = build(:user, encrypted_password: "") #Intentionally empty the confirmation password
user.valid?
expect(user.errors[:encrypted_password]).to include("Please enter", "Please enter at least 7 characters")
end
end
end
At this point, the following tests have been completed.
#Completed test ▼
Nickname required#Done
Email address is unique#Done
mail address is@And domain must be included#Done
Password required#Done
Enter the password twice, including for confirmation#Done
User's real name is required for surname and first name#Done
User's real name Frigana is required for surname and first name respectively#Done
Date of birth is required#Done
#Test to be implemented ▼
Password must be at least 7 characters
Enter the user's real name in full-width
Let the user's real name Frigana be entered in full-width
Now, let's test the regular expression described earlier. First of all, the password is a test of 7 characters or more.
Test both ** what you want to happen and what you don't want to happen **.
user.spec.rb
require 'rails_helper'
describe User do
describe '#create' do
#abridgement
#Password character count test ▼
it "You can register if the password is 7 characters or more" do
user = build(:user, password: "1234567", encrypted_password: "1234567") #Set a 7-character password using the build method
expect(user).to be_valid
end
it "Cannot register if password is 7 characters or less" do
user = build(:user, password: "123456", encrypted_password: "123456") #Intentionally set a 6-character password to test if an error occurs
user.valid?
expect(user.errors[:encrypted_password]).to include("Please enter at least 7 characters")
end
end
end
Finally, we will test full-width input and full-width kana input.
user.spec.rb
require 'rails_helper'
describe User do
describe '#create' do
#abridgement
#Name full-width input test ▼
it 'family_Registration is not possible unless name is entered in full-width' do
user = build(:user, family_name: "Aio") #Intentionally enter half-width characters to generate an error
user.valid?
expect(user.errors[:family_name]).to include("Is an invalid value")
end
it 'first_Registration is not possible unless name is entered in full-width' do
user = build(:user, first_name: "Aio") #Intentionally enter half-width characters to generate an error
user.valid?
expect(user.errors[:first_name]).to include("Is an invalid value")
end
#Katakana full-width input test ▼
it 'family_name_Only full-width katakana can be registered for kana' do
user = build(:user, family_name_kana: "AIUEO") #Intentionally input hiragana to generate an error
user.valid?
expect(user.errors[:family_name_kana]).to include("Is an invalid value")
end
it 'first_name_Only full-width katakana can be registered for kana' do
user = build(:user, first_name_kana: "AIUEO") #Intentionally input hiragana to generate an error
user.valid?
expect(user.errors[:first_name_kana]).to include("Is an invalid value")
end
end
end
This completes the functional test according to the specifications. The final result is as follows.
user.spec.rb
require 'rails_helper'
describe User do
describe '#create' do
#Test when entered ▼
it "Registration is possible if all items are entered" do
user = build(:user)
expect(user).to be_valid
end
# nul:false, presence:True test ▼
it "Cannot register without nickname" do
user = build(:user, nickname: nil)
user.valid?
expect(user.errors[:nickname]).to include("Please enter")
end
it "Cannot register without email" do
user = build(:user, email: nil)
user.valid?
expect(user.errors[:email]).to include("Please enter")
end
it "Cannot register without password" do
user = build(:user, password: nil)
user.valid?
expect(user.errors[:password]).to include("Please enter")
end
it "encrypted_Cannot register without password" do
user = build(:user, encrypted_password: nil)
user.valid?
expect(user.errors[:encrypted_password]).to include("Please enter")
end
it "family_Cannot register without name" do
user = build(:user, family_name: nil)
user.valid?
expect(user.errors[:family_name]).to include("Please enter")
end
it "family_name_Cannot register without kana" do
user = build(:user, family_name_kana: nil)
user.valid?
expect(user.errors[:family_name_kana]).to include("Please enter")
end
it "first_Cannot register without name" do
user = build(:user, first_name: nil)
user.valid?
expect(user.errors[:first_name]).to include("Please enter")
end
it "first_name_Cannot register without kana" do
user = build(:user, first_name_kana: nil)
user.valid?
expect(user.errors[:first_name_kana]).to include("Please enter")
end
it "birth_Cannot register if there is no day" do
user = build(:user, birth_day: nil)
user.valid?
expect(user.errors[:birth_day]).to include("Please enter")
end
#Password character count test ▼
it "You can register if the password is 7 characters or more" do
user = build(:user, password: "1234567", encrypted_password: "1234567")
expect(user).to be_valid
end
it "Cannot register if password is 7 characters or less" do
user = build(:user, password: "123456", encrypted_password: "123456")
user.valid?
expect(user.errors[:encrypted_password]).to include("Please enter at least 7 characters")
end
#Email uniqueness constraint test ▼
it "Cannot register if there are duplicate emails" do
user = create(:user)
another_user = build(:user, email: user.email)
another_user.valid?
expect(another_user.errors[:email]).to include("Already exists")
end
#Test that requires confirmation password ▼
it "encrypted even if password exists_Cannot register without password" do
user = build(:user, encrypted_password: "")
user.valid?
expect(user.errors[:encrypted_password]).to include("Please enter", "Please enter at least 7 characters")
end
#Identity verification name full-width input test ▼
it 'family_Registration is not possible unless name is entered in full-width' do
user = build(:user, family_name: "Aio")
user.valid?
expect(user.errors[:family_name]).to include("Is an invalid value")
end
it 'first_Registration is not possible unless name is entered in full-width' do
user = build(:user, first_name: "Aio")
user.valid?
expect(user.errors[:first_name]).to include("Is an invalid value")
end
#Identity verification Katakana full-width input test ▼
it 'family_name_Only full-width katakana can be registered for kana' do
user = build(:user, family_name_kana: "AIUEO")
user.valid?
expect(user.errors[:family_name_kana]).to include("Is an invalid value")
end
it 'first_name_Only full-width katakana can be registered for kana' do
user = build(:user, first_name_kana: "AIUEO")
user.valid?
expect(user.errors[:first_name_kana]).to include("Is an invalid value")
end
end
end
Execute the following command in the terminal of the directory of the application that describes the test.
Terminal.
$ bundle exec rspec
Then, if the processing is performed as shown in the image below, the test is successful.
If you can understand the basic grammar, the process that causes an error and the process that does not generate an error, and understand each method, you can write code even if a new function is added.
If you have any concerns, please let us know in the comments! Thank you for watching until the end!
Recommended Posts