Continuation of Last time
Tests include ** unit tests ** to check if a single model or controller works as expected, such as controller specs or model specs, and to check the behavior of the entire program that integrates multiple models and controllers. There is a ** integration test **.
RSpec provides ** System Spec ** as one of these integration tests. (Similar tests have feature specs, but have been deprecated since Rails 5.1.)
System specs are especially useful as UI tests among integration tests.
Install ** Capybara ** to simulate browser operations. You can use it to click links and verify screen display in your tests.
In Rails 5.0 and later, Capybara is installed by default, so if it is not installed, install it from Gemfile.
group :test do
gem 'capybara'
end
$ bundle install
I will add it to the settings so that I can use the system specifications and Capybara in the test.
spec/rails_helper.rb
#Postscript
require 'capybara/rspec'
RSpec.configre do |config|
#Postscript
config.before(:each, type: :system) do
driven_by :rack_test
end
config.before(:each, type: :system, js: true) do
driven_by :selenium_chrome_headless
end
Now that the preparations are complete, let's create a spec file first.
$ rails g rspec:system projects
Capybara provides methods such as visit, fill_in, and click_link, so you can easily write scenarios for the functions you need in your app.
spec/features/projects_spec.rb
require 'rails_helper'
RSpec.describe "Projects", type: :system do
scenario "user creates a new project" do #The starting point of the same example as it
user = FactoryBot.create(:user)
#Login operation
visit root_path
click_link "Sign in"
fill_in "Email", with: user.email
fill_in "Password", with: user.password
click_button "Log in"
#Project creation
expect {
click_link "New Project"
fill_in "Name", with: "Test Project"
fill_in "Description", with: "Trying out Capybara"
click_button "Create Project"
expect(page).to have_content "Project was successfully created"
expect(page).to have_content "Test Project"
expect(page).to have_content "Owner: #{user.name}"
}.to change(user.projects, :count).by(1)
end
end
The system specs allow you to test similar to what the user does on the browser.
In addition to the above specs, Capybara offers many methods. Among them, I will introduce the ones that appear frequently.
** Open page **
visit "/fake/page"
** Click the link or button label **
click_on "A link or button label"
** Check the label of the checkbox **
check "A checkbox label"
** Uncheck the checkbox label **
uncheck "A checkbox label"
** Select a radio button label **
choose "A radio button label"
** Select an option from the select menu **
select "An option", from: "A select menu"
** Attach the file with the file upload label **
attach_file "A file upload label", "/some/file/in/my/test/suite.f"
** Verify that there is an element that matches the specified CSS **
expect(page).to have_css "h2#subheading"
** Verify that there is an element that matches the specified selector **
expect(page).to have_selector "ul li"
** Verify that the current path is the specified path **
expect(page).to have_current_path "/projects/new"
If there are multiple selectors specified on the page and Capybara gets angry with "It's ambiguous", you can solve it by limiting the scope.
#Click the link text with the specified class or id
within "#id or .class" do
click_link "click here!"
end
#Click the tag with the specified class or id
find('div.class input').click
#Click the first applicable tag on the entire page
first(input).click
#Click the last applicable tag on the entire page
last(input).click
You can see the test results from the console output, but Capybara uses a headless browser (a browser without a UI) to see the HTML that Rails returns to the browser.
scenario "guest adds a project" do
visit projects_path
save_and_open_page #The HTML returned at this point is saved
click_link "New Project"
end
HTML is saved by save_and_open_page, so you can check it by opening it in your browser.
This feature is useful, but it's a hassle to open the file manually every time, so install the Launchy gem and let it open automatically.
Gemfile
group :test do
gem 'launchy'
end
$ bundle install
The selenium-webdriver gem installed by default in Rails specifies the JavaScript driver to use for testing, but it seems that there is a compatibility problem with the default FireFox, so change the setting to use Chrome.
I want to separate the Capybara setting file, so I will start with the file reading setting of rails_helper.rb.
spec/rails_helper.rb
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
spec/support/capybara.rb
Capybara.javascript_driver = :selenium_chrome_headless
In a CI environment, it is not desirable to open a new browser window during the test run, so Capybara allows you to use a ** headless driver ** to meet those needs. Here, I'm setting up to run the test using Chrome's headless mode.
Finally, install the Webdriver gem.
Gemfile
group :test do
gem 'webdrivers'
end
You can test operations using JavaScript by passing the js: true option.
scenario "test name", js: true do
#Test content
end
In Capybara, with the default setting, the waiting time for acquiring the processing result is 2 seconds, but the processing may not be in time and the test may fail. You can optionally set the waiting time to avoid this.
spec/support/capybara.rb
Capybara.default_wait_time = 15 #Set to 15 seconds
This setting applies to the entire test suite, but test execution can be slower than necessary, so it's a good idea to consider using using_wait_time each time you need it.
scenario "test" do
using_wait_time(15) do #Waiting time is 15 seconds only in this block
#Test content
end
end
Recommended Posts