Tests that I have avoided because I thought it would be difficult. I'm about to start the service in earnest, so I'll write about what I learned as the first step to a solid understanding of testing. It's a so-called memorandum. Since I am a beginner myself, I will write from a beginner's point of view. I would be grateful if you could comment if there are more writing styles and methods like this!
We will introduce the rules. Well, without thinking about anything here
Gemfile
group :development, :test do
...abridgement...
gem 'rspec-rails'
end
group :development do
gem 'web-console' #It may have been originally listed.
end
After editing the Gemfile, do the usual bundle install.
First, you need to create a configuration file for RSpec. At the terminal
$ rails g rspec:install
Then the following files will be generated.
create .rspec
create spec
create spec/spec_helper.rb
create spec/rails_helper.rb
Add the following to the ***. Rspec *** file of the generated files.
.rspec
--format documentation
If you add the above, the test result will be output in an easy-to-read manner. You can think of it as writing the context and it that will come out later in stages. Well, I don't think it's a problem without it. By the way, if you add options other than the above, you can also output text and display in parallel, so if you want to have it, please check it out.
For the time being, the installation is complete. It is the work to write the test code from here.
RSpec can be executed by typing a command in the terminal. I haven't written any test code yet, but type the following code into the terminal to see if it actually works.
Terminal
$ bundle exec rspec
The above is the command to run the test. As a result, it is okay if the display below is displayed.
Terminal
No examples found.
Finished in 0.00031 seconds (files took 0.19956 seconds to load)
0 examples, 0 failures
From here, create test files such as models, controllers, roots, and views, and write test code.
The goal is to write and execute test code for model validation, which is a unit test.
The test code creates a spec file and writes it. Instead of creating and writing one file, place the spec file under spec / models / for the model test file and under spec / controllers / for the controller test file for easy understanding. I will.
*** Spec file naming convention *** The spec file will be named the corresponding class name_spec.rb. This time we will be testing the validation of the contact form (contact model / contact.rb), so the name will be "contact_spec.rb".
Now that you know about the file where you write the test code, write the super super super basic test code before actually writing it. *** Simple test code "Make sure 1 + 1 becomes 2" ***
sample_spec.rb
describe "hogehoge" do
it "1 +1 becomes 2" do
expect(1 + 1).to eq 2
end
end
Ignore vocabulary and give your own commentary.
sample_spec.rb
describe "hogehoge" do #describe(Meaning to explain)Create a group for this test.
it "1 +1 becomes 2" do #it "~~~"do~~~Write what test this code is doing in the part
expect(1 + 1).to eq 2 #This part is the formula that checks whether the test actually succeeds.
end
end
The formula of the above expect (1 + 1) .to eq 2 part is called expectation. ● expect(X).to eq Y If the value of the expression in the x part is equal to the value in the Y part like this, the test will succeed. The eq part is called the matcher.
A matcher is a condition in which a test is successful in an speculation. For example, as mentioned above, eq means "if equal". There are multiple other matchers such as include (if included) and valid (if validated). There are many, so please use it according to the test you want to write.
The contact model (inquiry function) used this time is as follows.
contact.rb
class Contact < ApplicationRecord
#Sender's name
validates :name, presence: true
#E-mail address to reply to inquiries
validates :email, presence: true, length: {maximum:255},
format: {with: /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i}
#Inquiry subject
validates :title, presence: true
#Content of inquiry
validates :message, presence: true
end
We will write test code for the above validation.
Edit the created contact_spec.rb as follows.
contact_spec.rb
require 'rails_helper'
RSpec.describe Contact, type: :model do
it "Cannot register without name" do
end
end
The first line require'rails_helper' enables common settings by reading the description in rails_helper.rb. This first line description is written to every spec file every time.
Once I wrote it, execute the command bundle exec rspec in the terminal. I haven't written an expression that evaluates as a test yet, so the test passes unconditionally. It's okay if it looks like the following.
Terminal
Terminal
Contact
Cannot register without name
Finished in 0.23784 seconds (files took 4.71 seconds to load)
1 example, 0 failures
Add the following to the test code you wrote earlier.
contact_spec.rb
RSpec.describe Contact, type: :model do
it "Cannot register without name" do
contact = Contact.new(name: "", email: "[email protected]", title: "About returns", message: "I would like to return the item with order number 000000000.")
contact.valid?
expect(contact.errors[:name]).to include("Please enter")
end
end
*** [3rd line] Create a new instance of contact class with the property you want to test in ***. I want to create a test code to confirm that "cannot be registered if name is empty", so I am creating an instance of contact class with the value of name empty and other values set appropriately.
*** [6th line] Check if the instance created in *** cannot be saved by validation.
As a result of checking with *** [7th line] ***, check whether the error statement of the instance is what you expected. If you specify the column name in the hash value retrieval method for contact.errors, you can retrieve the array containing the error statement caused by that column. For this, we are making an exemption using a matcher called include. This time, "Please enter" is output in the validation error statement, so the content is described.
The above flow has the same meaning as the verification on the console below.
Terminal
#Launch the console
$ rails c
#Create an instance of the contact class with an empty name value
>contact = Contact.new(name: "", email: "[email protected]", title: "About returns", message: "I would like to return the item with order number 000000000.")
#valid?Use the method
>contact.valid?
#Use the errors method
>contact.errors
=> #<ActiveModel::Errors:0x007ffa6ce07ef0
@base=
#<Contact:0x007ffa6d3430b8
#Omission
@messages={:name=>["Please enter"]}>
Now enter the RSpec command to run the test.
Terminal
$ bundle exec rspec
If you get the following result, you are successful.
Terminal
Contact
Cannot register without name
Finished in 0.07346 seconds (files took 2.31 seconds to load)
1 example, 0 failures
If an error is displayed, an error message will be displayed in the terminal and can often be resolved by reading it carefully. Also, as mentioned above, if you check it once as a series of flows on the console, I feel that your understanding will deepen a little.
I wrote one test code earlier, but when writing a test for mail other than name, it will be as follows.
contact_spec.rb
RSpec.describe Contact, type: :model do
it "Cannot register without name" do
contact = Contact.new(name: "", email: "[email protected]", title: "About returns", message: "I would like to return the item with order number 000000000.")
contact.valid?
expect(contact.errors[:name]).to include("Please enter")
end
it "Cannot register without email" do
contact = Contact.new(name: "takashi", email: "", title: "About returns", message: "I would like to return the item with order number 000000000.")
contact.valid?
expect(contact.errors[:email]).to include("Please enter")
end
end
I'm simply emptying the email part, but creating an instance each time increases the amount of code. *** factory_bot *** improves this.
A Gem that allows you to easily create a dummy instance. Set the properties defined for each class instance in advance in another file, and use the method from the spec file to create the exact instance.
If you use factory_bot, the description will be as follows.
contact_spec.rb
RSpec.describe Contact, type: :model do
it "Cannot register without name" do
contact = build(:contact, name: "")
contact.valid?
expect(contact.errors[:name]).to include("Please enter")
end
it "Cannot register without email" do
contact = build(:contact, email: "")
contact.valid?
expect(contact.errors[:email]).to include("Please enter")
end
end
I created an instance in a separate file in advance and called it.
*** Added gem'factory_bot_rails' *** to the same environment as rspec-rails
Gemfile
group :development, :test do
#abridgement
gem 'rspec-rails'
gem 'factory_bot_rails'
end
Then bundle install and Create a directory called "factories" directly under the spec directory. In it, create a Ruby file with the plural filename of the created instance. In this case, it's contacts.rb.
Edit the created contacts.rb file as follows.
contacts.rb
FactoryBot.define do
factory :contact do
name {"takashi"}
email {"[email protected]"}
title {"About returns"}
message {"I would like to return the item with order number 000000000."}
end
end
Then, when creating an instance, you can create an instance with the contents of the set template by writing the following.
#factory_When not using a bot
contact = Contact.new(name: "", email: "[email protected]", title: "About returns", message: "I would like to return the item with order number 000000000.")
#factory_When using a bot
contact = FactoryBot.build(:contact)
It was pretty refreshing. Also, by editing spec / rails_helper.rb as follows, you can omit the description of FactoryBot of the class that is the receiver.
rails_helper.rb
RSpec.configure do |config|
#Added the following description
config.include FactoryBot::Syntax::Methods
#abridgement
end
Based on the above, I will write additional test code.
contact_spec.rb
require 'rails_helper'
RSpec.describe Contact, type: :model do
it "Cannot register without name" do
contact = build(:contact, name: "")
contact.valid?
expect(contact.errors[:name]).to include("Please enter")
end
it "Cannot register without email" do
contact = build(:contact, email: "")
contact.valid?
expect(contact.errors[:email]).to include("Please enter")
end
it "@Domain after the mark" do
contact = build(:contact, email: "example@eee")
contact.valid?
expect(contact.errors[:email]).to include("Is an invalid value")
end
it "Cannot register without title" do
contact = build(:contact, title: "")
contact.valid?
expect(contact.errors[:title]).to include("Please enter")
end
it "Cannot register without message" do
contact = build(:contact, message: "")
contact.valid?
expect(contact.errors[:message]).to include("Please enter")
end
end
This is the completed form for the time being.
This time, we ran a test on the validation of the contact model, but there are various ways to write it depending on the specifications of the WEB application. I hope it helps you to understand the world of testing as much as possible. It seems that the method of testing the controller will be different, so I hope to improve it soon.
As I understood the test a little, I came to think that when developing the next application, I would like to write the test code and then implement it. We would appreciate it if you could comment on any corrections or corrections to the content of the article.
Thank you for reading for a long time!
Recommended Posts