So far, we have written test specifications to test Dave Haeffner's The-Internet, and we have set up the Gauge-Ruby environment. We managed to get Chrome to run a simple Capybara test, and figured out how to make the test run in Headless Chrome. Our test we created last time...
specs/Navigation/Navigation.spec
# Navigation: Go to The-Internet Login Page
## NAVIGATION: Visit The-Internet
* LOGIN: Visit the Login Page
* LOGIN: Verify the heading is "Login Page"
... For this entry, we will be building upon that, figuring out how to get our Capybara-Gauge framework to execute the following:
Authorization: Validate logging into and out of The-Internet
- Scenario #1: Authorization: Successfully log into and out of the secure area
- Scenario #2: Authorization: Verify alert error is shown when entering a blank user name and password.
Create A Smoke Test
How did we want to test The-Internet? One way to do it:specs/Authorization/SmokeTests.spec
Authorization: Validate logging into and out of The-Internet
- LOGIN: Visit the Login Page
- LOGIN: Verify heading: "Login Page"
- LOGIN: Log into the site using username and password: "tomsmith" and "SuperSecretPassword!"
- SECURE AREA: Verify heading: "Secure Area"
- SECURE AREA: Log out of the secure area
- LOGIN: Verify heading: "Login Page"
- LOGIN: Log into the site using username and password: " " and " "
- LOGIN: Verify alert message: "Your username is invalid"
Notice that you can't start logging in and out of the secure page or entering invalid data without actually visiting the Login Page (making sure that the page has the proper heading, as a verification step).
I decided, to make it more readable, to explicitly spell out where I am going and what I am verifying. Because both steps, the visiting and the verifying is shared between the two scenarios, I pulled them out to the top, so they will be run before any of the scenarios execute.
Next, let's tackle implementing that first step....
Create Login Step Implementation
Let's look at that first step for specs/Authorization/SmokeTests.spec:## Authorization: Successfully log into and out of the secure area
* LOGIN: Log into the site using username and password: "tomsmith" and "SuperSecretPassword!"
... How would we automate it?
We could create in the step_implementations section a new folder called "Authorization" with a file called SmokeTests.spec, and start building out the automation:
- Require the Spec Helper
- Write the test step
- Find the page elements
- Team Capybara's Github: https://github.com/teamcapybara/capybara
- Zhengjia's Capybara Cheat Sheet: https://gist.github.com/zhengjia/428105
- Capybara's README: https://www.rubydoc.info/github/teamcapybara/capybara
- Capybara's Google Groups: https://groups.google.com/forum/#!forum/ruby-capybara
- Gauge's documentation: https://docs.gauge.org
- Gauge's Manual: https://manpage.gauge.org/
Require the Spec-Helper
We did a lot of work configuring Chrome to work with Gauge. Let's make sure to require that step_implementations/login_spec.rb uses this data:- require_relative 'spec_helper'
Write Test Steps For Login
Gauge has two main parts to its framework:- Specs: The human readable test cases and scenarios that will be included in the reports. Test steps are indicated as bullet points.
- Step Implementations: Each bullet point in the spec needs a corresponding step component that lists what needs to be done.
Let's take the first test scenario, for instance. We could write it like:
## Authorization: Successfully log into and out of the secure area
* LOGIN: Log into the site using username and password: tomsmith and SuperSecretPassword!
... But what happens if you want to enter other usernames or passwords? We would need a new spec for each username and password combination. Instead, we can make the step we will be creating to be data driven, indicating that the username and password are variables by putting quotes around the value.
## Authorization: Successfully log into and out of the secure area
* LOGIN: Log into the site using username and password: "tomsmith" and "SuperSecretPassword!"
We can then write the corresponding step where the value "tomsmith" is passed into a variable, "username", and "SuperSecretPassword!" is passed into the variable "password":
step_implementations/login_spec.rb
step 'LOGIN: Log into the site using username and password: <username> and <password>' do |username, password|
## Enter data here
end
Find The Login Page Elements
Take a look at the elements on the Login Page at https://the-internet.herokuapp.com/login
You have a Login Header, a Username Field, a Password Field, and a Login Button. And if you hit the Login button without filling in the username or password, you get an alert message.
Capybara can automatically find web elements by label. In my experience, throughout the life of an app, Labels constantly change. Labels get longer, shorter, or get modified. "Username" could be changed to "User" in the next iteration. Right now, the Login button is labelled "Login", but it could also changes.
Capybara can automatically find web elements by css selector or id. Select the LOGIN button without entering text, and you see the alert message "Your username is invalid". With Chrome, if you Right-Click and select "Inspect", in Chrome Developer Tools you can see that the data alert is contained in a DIV with the id "flash-messages". This ID can also change.
If we store the locators on the top of the page in a Ruby constant, we won't have to start digging through the code the next time they change.
step_implementations/login_spec.rb
- LOGIN_HEADER = 'h2'
- USERNAME_FIELD = 'Username'
- PASSWORD_FIELD = 'Password'
- ALERT_MESSAGES = 'flash-messages'
- LOGIN_BUTTON = 'Login'
Create The Login Step
Capybara has two methods we can use: fill_in and click_button. But what happens if we receive errors? How would we be able to know how the fields were actually filled out?
Gauge gives us a method called "write_message", where we can send messages to the HTML report.I love this feature! Never trust Green. Make sure you review the report produced after a successful run to make sure that your test framework is doing what you expect it to do.
Using these methods, combining it with the page elements created, we get for login_spec.rb:
step 'LOGIN: Log into the site using username and password: <username> and <password>' do |username, password|
Gauge.write_message("\t* Entering Username: '#{username}'")
fill_in(USERNAME_FIELD, with: username)
Gauge.write_message("\t* Entering Password: '#{password}'")
fill_in(PASSWORD_FIELD, with: password)
click_button(LOGIN_BUTTON)
end
Notice that when we were creating login_spec.rb, we really didn't generate that much code. Capybara does most of the heavy lifting when it comes to waiting for page elements to load, sending keys, and pressing buttons.
Normally, I would encapsulate each action I can do on the page in its own public method, contained in a page object. With Gauge, it already has each action set up in each step. The Gauge.org people prefer it this way, writing blog posts about how they dislike the Page Object Pattern ("The Page Objects anti pattern"). ... When in Rome! ...
Write Test Steps for Secure Area
Next, we are going to be implementing the Secure area steps...- SECURE AREA: Verify heading: "Secure Area"
- SECURE AREA: Log out of the secure area
secure_area_spec.rb
require_relative 'spec_helper'
SECURE_HEADER = 'h2'
LOGOUT_BUTTON = '#content > div > a > i'
step 'SECURE AREA: Verify heading: <page_header>' do |page_header|
expect(SECURE_HEADER).to have_content(page_header)
end
step 'SECURE AREA: Log out of the secure area' do
find(LOGOUT_BUTTON).click
end
Why did we write the validation step verifying the heading with the variable "page_header"? Labels and headers change all the time. They should not be hardcoded. If the "Secure Area" page was given a new heading, such as "Secure Section", I only want to change the test specification. I don't want to dig into the code itself.
Likewise, as before, I lifted out the locator of the Logout button, placing that into a Ruby constant.
Two things I want to point out:
The Expect Method:
- Are you definitely expecting something to show up immediately, within the next ten seconds? Using expect is fine.
- Are you dealing with a slow loading component or a slow loading page? Rewrite the code so it will wait for whatever you designated in the spec_helper.rb file as the TIMEOUT: (SECURE_HEADER).should have_content(page_header)
- Sometimes you want more control over where you are searching for a certain element. Fill_in and click_button search the entire page by default. You can choose to find the element first, then use the click method to click on the element... if, of course, it is clickable.
Make Sure To Reuse Steps!
How do we make sure that we are successfully returned to the Login page? Check the page header!... Wait, don't we already have a step created for this?
- LOGIN: Verify heading: "Login Page"
All we need to do is add that line to the scenario, and we are all set!
Does Everything Still Run?
Run all Authorization/SmokeTests.spec test cases in verbose mode to make sure everything still works and see the output of each step:
- bundle exec gauge run specs/Authorization -v
- bundle exec gauge run specs -v
Verifying the Alert Errors
Next, we have the following scenario to automate:Authorization: Verify alert error is shown when entering a blank user name and password.
- LOGIN: Log into the site using username and password: " " and " "
- LOGIN: Verify alert message: "Your username is invalid"
If we were to trigger an error by entering the LOGIN button without any data, and in Google Chrome we Inspect that field, we can see that the area is called "flash-messages".
The code we can add to login_spec.rb to handle this test:
ALERT_MESSAGES = 'flash-messages'
step 'LOGIN: Verify alert message: <alert_message>' do |alert_message|
expect(ALERT_MESSAGES).to have_content(alert_message)
end
This gives us our final version:
step_implementations/login_spec.rb:
require_relative 'spec_helper'
APP_URL = 'https://the-internet.herokuapp.com/login'
LOGIN_HEADER = 'h2'
USERNAME_FIELD = 'Username'
PASSWORD_FIELD = 'Password'
ALERT_MESSAGES = 'flash-messages'
LOGIN_BUTTON = 'Login'
step 'LOGIN: Visit the Login Page' do
Gauge.write_message("Navigating to: '#{APP_URL}'")
visit(APP_URL)
end
step 'LOGIN: Verify heading: <page_header>' do |page_header|
expect(LOGIN_HEADER).to have_content(page_header)
end
step 'LOGIN: Log into the site using username and password: <username> and <password>' do |username, password|
Gauge.write_message("\t* Entering Username: '#{username}'")
fill_in(USERNAME_FIELD, with: username)
Gauge.write_message("\t* Entering Password: '#{password}'")
fill_in(PASSWORD_FIELD, with: password)
click_button(LOGIN_BUTTON)
end
step 'LOGIN: Verify alert message: <alert_message>' do |alert_message|
expect(ALERT_MESSAGES).to have_content(alert_message)
end
Running the test we can see that everything passed! Check the tests in the Navigation + Authorization section:
- Mac Terminal: bundle exec gauge run specs -v
- HEADLESS = false
- HEADLESS = true
- gauge install html-report
- More information from the Gauge GitHub page.
Did you install the XML-REPORT Plugin?
- gauge install xml-report
- More information from the Gauge GitHub page.
Did you install the JSON-REPORT Plugin?
- gauge install json-report
Unsure of what your setup is?
- gauge version
View Reports Produced
Want to see some sample reports generated by running the finished product? Take a look at the project directory on GitHub of my capybara-gauge project:
- html-report results, rendered through GitHub's HTML Preview
- xml-report results: Not very detailed
- json-report results: Very detailed!
Next, let's make things interesting, editing the spec_helper.rb file to add Chrome and Chromedriver logging...
Happy Testing!
Basic Capybara-Gauge:
- Part One: Analyzing The-Internet
- Part Two: Setup Ruby Environment
- Part Three: Setup Capybara to Test Opening Chrome
- Part Four: Add Option For Chrome Headless
- Part Five: Add Test Steps and Spec Implementations
- Part Six: Setup Chrome and ChromeDriver Logging
- Part Seven: Rubocop Code Review
- Source Code: https://github.com/tjmaher/capybara-gauge
-T.J. Maher
Sr. QA Engineer, Software Engineer in Test
Meetup Organizer, Ministry of Testing - Boston
Twitter | YouTube | LinkedIn | Articles
3 comments:
Aivivu chuyên vé máy bay, tham khảo
gia ve may bay di my
chuyến bay từ mỹ về vn
khi nào có chuyến bay từ nhật về việt nam
bao giờ có chuyến bay từ đức về việt nam
giá vé máy bay từ canada về Việt Nam
mua vé máy bay từ hàn quốc về việt nam
Chuyen bay cho chuyen gia nuoc ngoai
Hello thanks for posting this
This blog took me back to my days balancing Capybara setups with exam prep. Setting up specs and step implementations was intense! During that time, I opted for a service to “do my exam for me.” It was a lifesaver, letting me focus on the technical work without the added stress of exams. If you’re in the same boat, getting some help could make all the difference!
Post a Comment