Practical Web Test Automation Sample PDF
Practical Web Test Automation Sample PDF
Practical Web Test Automation Sample PDF
Zhimin Zhan
This book is for sale at http://leanpub.com/practical-web-test-automation
This is a Leanpub book. Leanpub empowers authors and publishers with the Lean
Publishing process. Lean Publishing is the act of publishing an in-progress ebook using
lightweight tools and many iterations to get reader feedback, pivot until you have the right
book and build traction once you do.
Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . i
Who should read this book? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ii
How to read this book? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . iii
What’s inside the book? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . iii
Test scripts, Screencasts and other resources . . . . . . . . . . . . . . . . . . . . . . iv
Send me feedback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . iv
Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . v
5. Case Study . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
5.1 Test site . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
5.2 Preparation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
5.3 Create test project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
5.4 Test Suite: Sign in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
5.5 Test Suite: Select Flights . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
5.6 Enter passenger details . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
5.7 Book confirmation after payment . . . . . . . . . . . . . . . . . . . . . . . . 48
5.8 Run all tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
5.9 Wrap up . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
Preface
On April 3 2013, Wired published an article “The Software Revolution Behind LinkedIn’s
Gushing Profits”¹. The revolution “completely overhauled how LinkedIn develops and ships
new updates to its website and apps, taking a system that required a full month to release new
features and turning it into one that pushes out updates multiple times per day.” LinkedIn
is not alone, Google has accomplished this long before that. As a matter of fact, LinkedIn’s
success is tracked back to luring a Google veteran in 2001. “Facebook is released twice a
day”² and they claimed “keeping up this pace is at the heart of our culture”³.
Release software twice a day! For many, that’s unimaginable. You may wonder how they
could ensure quality (and you know the high standard from them). The answer is, as the
article pointed out, to use “automated tests designed to weed out any bugs.”
After working on numerous software projects for a number of years, I witnessed and
had been part of many what I call ‘release panic syndromes’. That is, with the deadline
approaching, the team’s panic level rises. Many defects were found from the last round of
manual testing by the testers. The manager started priortizing the defects (or adjusting some
to features), and programmers rushed to fix just the critical ones. Testers restarted the testing
on the new build that had fixed some but not all the defects. Then here came the bad news:
several previously working features are now broken, Argh!
I believe there is a better way to do software development that does not have to involve this
kind of stress and panic. This is how my interest in automated testing started (in 2006). I
made the right decision to use free, open source and programming based test frameworks.
(It is quite obvious now, as Selenium WebDriver is the best sought after testing skill on
the job market. Back then, people turned to record/playback commercial tools with vendor
proprietary test script syntax). The first test framework I used (for my pet projects) was
Watir. I was quickly convinced that this approach was the answer.
In 2007, I had the opportunity to put my approach into practices in a government project.
The outcome was beyond everyone’s expectation: over two years and countless releases,
there were no major defects reported by customers. The team had high confidence in the
product. These automated tests also provided the safety net for some major refactorings,
¹http://www.wired.com/business/2013/04/linkedin-software-revolution/
²http://www.facebook.com/notes/facebook-engineering/ship-early-and-ship-twice-as-often/10150985860363920
³http://www.seleniumconf.org/speakers/
Preface ii
which would have not been possible without them. A business analyst once said, “before
every demonstration to our customers, it is a good feeling of knowing every release has
been thoroughly tested.” The synergy of flexible test framework, maintainable test design,
team collaboration with the same simple testing tool and continuous integration supporting
functional test execution really made a big difference.
There is now a clearly converging trend in web application development on technology
choices, such as cloud deployment, light and productive web frameworks such as “Ruby on
Rails”⁴, JQuery JavaScript Library, Twitter BootStrap UI themes, Font Awesome icons, …, etc.
The competitions among web applications are less on technologies, but weigh more on the
development process to ensure pushing out high quality releases frequently. A fact: Facebook
was not the first social networking web site.
A friend of mine, who developed a quite successful public web application, told me in an
uneasy tone that he just found out another competitor product at a cheaper price. This is
inevitable, the competition among web applications is global, which means, there are people
working at 10% of your hourly rate to compete against you. The only way to win the race, in
my opinion, is to greatly enhance your productivity and reduce maintenance cost. This can
be achieved by applying test automation and continuous integration with instant benefits
without much effort (if doing it properly). My reply to my friend: “If your competitors start
to invest in test automation seriously, you shall be worried.”
In Appendix II, I share my experience on developing ClinicWise, a modern web-based
clinic management system. Thanks to comprehensive automated UI testing, ClinicWise is
frequently released (daily) with new features and updates. ClinicWise is developed and
maintained in my spare time.
The purpose of this book is to share my journey of test automation for web applications:
from writing the first test to developing and maintaining large number of automated test
scripts.
Prior experience with automated testing is not necessary. Basic programming concepts will
help, but again, not necessary.
In Part 5, I switch the attention to several WebDriver backed variant frameworks: Watir,
RWebSpec and Capybara and introduce another test syntax framework Cucumber⁶. Then I
will show how to apply the maintainable test design and techniques to them. Finally I share
some strategies to apply test automation to your project.
• Software. Test automation is not necessarily expensive. All test frameworks featured
in this book are free and open-sourced. Testing tools used for the exercises in this book
are also free, and there are instructions to cater for other text-based testing tools.
• Sample test scripts. The sample test scripts for the exercises are ready-to-run. This
book covers several popular test and syntax frameworks: Selenium-WebDriver, Watir,
RWebSpec, RSpec and Cucumber. To help readers understand the differences, I have
created 6 test projects with different combinations: https://github.com/testwisely/agiletravel-
ui-tests⁸.
• Sample web sites. For readers who need web sites to try out automated test scripts, I
have prepared two test sites for you:
– Agile Travel: a simple flight booking site, which is used in the exercises.
– AdminWise: a feature rich web 2.0 site with modules such as membership and
library.
• Tutorial screencasts. There are screencasts for readers who will learn better with
audio and video, so you will be able to see how it is done step by step.
Send me feedback
I will appreciate hearing from you. Comments, suggestions, errors in the book and test scripts
are all welcome. You can submit your feedback on the book web site (http://zhimin.com/books/pwta).
⁶http://cukes.info/
⁷http://zhimin.com/books/pwta
⁸https://github.com/testwisely/agiletravel-ui-tests
Preface v
Acknowledgements
I would like to thank everyone who sent feedback and suggestions, particularly Mingli Zhou,
Darren James, Tim Wilson, Lloyd Blake, Hoang Uong and Lien Nguyen, for their time and
wisdom.
I owe a huge ‘thank you’ to people behind great open-source testing frameworks such as
Selenium-WebDriver and RSpec, and of course, the beautiful Ruby language.
Functional testing via User Interface is practical and light on theory, so is this book. I hope
you find this book useful.
Zhimin Zhan
Brisbane, Australia
1. What is Web Test Automation?
Web Test Automation, or automated functional testing for web applications via the Graphical
User Interface (GUI), is the use of automated test scripts to drive test executions to verify
that the web application meets its requirements. During execution of an automated test for
a web site, you see mouse and keyboard actions such as clicking a button and typing text
in a text box in a browser, without human intervention. Web Test Automation sits under
the category of black-box functional testing, where the majority of test efforts is in software
projects.
• Reliable. Tests perform the same operations precisely each time they are run, therefore
eliminating human errors.
What is Web Test Automation? 2
Michael Feathers was spot on summarizing the status of automated end-to-end testing. Over
last 10 years, I pretty much experienced the same: software teams were either ‘pretending
automated UI testing’ or ‘not doing it at all’.
• lack of time
• lack of budget
• lack of expertise
These reasons sound right to most people. However, saving time and money are two benefits
of test automation, isn’t that a contradiction (for lack of time and budget)? What are the
real difficulties or challenges, apart from political or project management ones, that projects
encounter during their adventures in automated testing?
To make it easy to understand, we can compare a project’s test automation attempt with a
person who is trying to climb over a standing two-hump camel from the front. Let’s consider
each of the following challenges he faces:
What is Web Test Automation? 4
change to the application can ruin your hours of recording). When testers have to open the
raw test scripts (generated by recorders) to edit, reality bites.
Open source test frameworks, on the other hand, require some degree of programming
efforts, Selenium-WebDriver and Watir are among the popular ones. With programming,
they provide flexibility needed for automated testing. However, the fact is that the majority
of software testers do not possess programming skills, and many of them feel uncomfortable
to learn it. Besides, there are few dedicated testing tools supporting these open-source test
frameworks designed to suite testers. (Programming IDEs are designed for programmers,
not for testers who may find them complicated and overwhelming).
3. Hump 1: Hard to maintain
Software under development changes frequently, and automated UI test scripts are vulner-
able to application changes. Even a simplest change to the application could cause many
existing test scripts fail. This, in my view, is the most fundamental reason for test automation
failures.
4. Hump 2: Long feedback loop
Compared to programmer tests (which if written well, should have an execution time under
0.1 second), automated functional tests through UI are relatively slow. There is practically
very little that testers can do to speed up execution of functional tests. With the number
of test cases growing, so will be the test execution time. This leads to long feedback gap,
from the time programmers committed the code to the time test execution completes. If
programmers continue developing new features or fixes during the gap time, it can easily
get into a tail-chasing problem. This will hurt team’s productivity, not to mention team’s
morale.
New Challenges for testing Web applications
Specifically to web applications, with adoption of AJAX (Asynchronous JavaScript and XML)
and increasing use of JavaScript, websites nowadays are more dynamic, therefore, bring new
challenges to web test automation.
Is that all possible? My answer is ‘Yes’. The purpose of this book is to show how you can
achieve these.
If you are Mac user, like myself, the learning process is the same (majority of the test
scripts run without change) except the screenshots shown in the book look different. All
the techniques and test scripts are directly applicable for cross-browser testing.
On testing tools, I use TestWise, a testing IDE that supports Selenium WebDriver and Watir
(TestWise has free 30-day trial), in this book. For readers who prefer their own favorite
editors or IDEs, you can still use them, as all test scripts shown in this book are plain text. I
will also provide instructions on how to execute tests from the command line.
Example test scripts for chapters in this book can be downloaded at the book site, and you
can try them out by simply opening in TestWise and run. I have provided screencasts there
as well, readers can watch how it is done.
In this book, we will focus on testing standard web sites (in HTML), excluding vendor specific
and deprecated technologies such as Flash and SilverLight. The techniques shown in this
book are applicable to general testing practices.
What is Web Test Automation? 7
Let’s write an automated web test. If you are new to automated testing, don’t feel intimi-
dated. You are going to see your first automated test running in Internet Explorer in about
10 minutes, and that includes installing the test tool!
• TestWise Recorder.
TestWise Recorder is a Chrome extension, which records your operations into exe-
cutable Selenium WebDriver and Watir test scripts while you navigates through your
web application in Chrome. To install, search for “TestWise Recorder” in Chrome Web
Store page³, click “+ ADD TO CHROME” button. Click the recorder icon on toolbar to
enable recording.
Enable recorder
Now we are ready to create the test for our requirement: “User can login the site”. Hope you
still remember the test design steps and test data.
TestWise has a project structure to organize test scripts. This structure is simply a folder
containing all test related files such as test scripts and test data.
As we start from scratch, we need to create a new project first. If a sample project is already
opened in TestWise, we need to close it. Select menu File → New Project, which will bring
up the window shown below.
³https://chrome.google.com/webstore/detail/testwise-recorder/febfogamlejngokejcaimklgcfphjbok
First Automated Test 11
Create Project
Enter project name, project folder and URL of web site to be tested. In this case, we enter
“Agile Travel”, “C:\testprojects\AgileTravel” and “http://travel.agileway.net” respectively,
then click ‘OK’ button. TestWise will create the project with skeleton files.
Project Skeleton
Now create the test script file for our test. Select ‘File’ → ‘New File’,
First Automated Test 12
New test
Type text ‘login’ and press Enter to create new test script file: login_spec.rb
Try naming the test script file something related to the requirement, so you can
find it easily later.
Login test
Recording
Open the site URL http://travel.agileway.net in Firefox and enable ‘TestWise Recorder
SideBar’. Perform the test steps below manually:
1. Enter username ‘agileway’
2. Enter password ‘testwise’
First Automated Test 13
Recording
Test steps are recorded along the way. Once done, inside the TestWise Recorder window,
click ‘Copy’ button on top to copy recorded test steps to clipboard.
The test case is created. While we are here, update the test suite name (the string in describe
"..." ) to “User Authentication” and the test case’s name (the string in it "..." do) to “User
can login with valid user name and password”.
The first two copied steps:
start Chrome browser and navigate to our target server. You can delete them if using
TestWise, as they are already included in before(:all) block (created by TestWise in a more
generic format). The test scripts in the TestWise shall be like the below:
before(:all) do
@driver = $browser = Selenium::WebDriver.for(browser_type)
@driver.navigate.to(site_url)
end
after(:all) do
@driver.quit unless debugging?
end
end
Select the Chrome browser icon and press on the tool bar (highlighted in the screenshot
below) to run the test case, and you can watch the test execution in a Chrome window.
The browser_type and site_url are defined in test_helper.rb, which you can easily
modify. More importantly, with IDE support, you can run tests against another target
server (in Project settings) and browser quickly in IDE. Feel free to change the target
browser to Firefox or IE (provided that the browser and its webdriver are installed
correctly) and run the test again.
If you want to set the browser type and server URL specifically in each individual test
script, you can.
@driver = $browser = Selenium::WebDriver.for(:firefox)
@driver.get("http://travel.agileway.net")
TestWise run
Test failed
In TestWise, the test execution is marked as “Failed” and is shown on line 18 of the test
script indicating where the failure is.
We, as human, knew the reason for this failure: a wrong password was provided. From the
test script’s “point of view”, it failed due to this assertion not met: finding the text “Welcome
agileway” on the page.
If you want to find more details about the cause for test failure, check the text output of test
execution including error trace under “Test Output” tab.
2.7 Wrap up
Let’s review what we have done in this chapter. Besides test design, we
First Automated Test 18
Hopefully you were able to do all that within 10 minutes! You can view the screencast for
this exercise online at the book’s website at http://zhimin.com/books/pwta⁴.
⁴http://zhimin.com/books/pwta
3. How Automated Testing works
In the previous chapter, we created an automated functional test running in a web browser,
Chrome. This was done by simulating a user interacting with the browser: typing texts and
clicking buttons.
Before we move on, let us examine our test targets - web applications (or websites). Simply
speaking, a web site consists of many web pages. Behind each web page there is an HTML
(HyperText Markup Language) file. Browsers download the HTML files and render them.
HTML defines a set of standard web controls (aka elements) we are familiar with, such as
text boxes, hyperlinks, buttons, check boxes, etc. For web application testing, we interact
with these controls as well as the texts that get marked up in the HTML such as labels and
headings.
Now let us review the test script we created in the last exercise:
Within a test case, test steps can be classified into the following two categories:
driver.find_element(:id, "username").send_keys("agileway")
driver.find_element(:id, "password").send_keys("testwise")
driver.find_element(:xpath,"//input[@value='Sign in']").click
• Check (also called assertion)
Verifying the web page meets the requirement.
the_page_text = driver.find_element(:tag_name, "body").text
expect(the_page_text).to include("Welcome agileway")
Selenium WebDriver
Selenium was originally created in 2004 by Jason Huggins, who was later joined by his other
ThoughtWorks colleagues. Selenium supports all major browsers and tests can be written in
many programming languages and run on Windows, Linux and Macintosh platforms.
Selenium 2 is merged with another test framework WebDriver led by Simon Stewart at
Google (that’s why you see ‘selenium-webdriver’), Selenium 2.0 was released in July 2011.
Here is an example test in Selenium WebDriver:
require "selenium-webdriver"
driver = Selenium::WebDriver.for(:firefox) # or :ie, :chrome
driver.navigate.to "http://www.google.com"
driver.find_element(:name, "q").send_keys "WebDriver IDE"
driver.find_element(:name, "btnG").click #"btnG" is the 'Search' button
Its HTML source (you can view the HTML source of a web page by right clicking in the web
page and selecting “View Page Source”):
Though the username and password appear the same (text box) on the browser, they are
quite different in source. Some attributes in HTML tags tell web browsers how to render
it, such as size=”20” in user name text box. More importantly, application developers use
attributes such as “name” (not exclusively) to determine user’s input is associated to which
control.
We can identify web controls by using these attributes for testing. Here is one way to identify
them in Selenium:
driver.find_element(:name, "username")
driver.find_element(:id, "pwd_box")
driver.find_element(:xpath,"//input[@value='Sign in']")
As you can see, these three test steps use three different attributes for three controls.
Obviously the easiest way to identify web controls is to use a recorder (a tool records user’s
operation and generate test scripts), if you have one installed. However, in my opinion, it is
essential for technical testers to master and be comfortable to do it manually. The reasons
are:
• Some test frameworks don’t have recorders or have outdated ones
• Recorders might not work for certain circumstances
How Automated Testing works 22
Inspect in Chrome
Check
The purpose of testing is to verify that a piece of function serves its purpose. After ‘driving’
the application to a certain point, we do checks (maybe that’s why it is called ‘checkpoint’
in some testing tools).
How Automated Testing works 23
xUnit
xUnit (JUnit and its cousins) test frameworks are widely used for unit testing by program-
mers. xUnit can be used in functional test scripts too, but it is not my preference, as it is not
as expressive as the ones below.
RSpec
RSpec is a popular Behaviour Driven Development (BDD) framework in Ruby.
More expressive
Comparing to xUnit test frameworks, RSpec tests are easier to read. For example, for the
JUnit test below:
How Automated Testing works 24
class UserAuthenticationTest {
public void testCanLoginWithValidUsernameAndPassword {
// ...
}
public void testAccessDeniedForInvalidPassword() {
// ...
}
}
Execution Hooks
Execution hooks are similar to setUp() and tearDown() functions in JUnit. Test steps inside
a execution hook are run before or after test cases depending on the nature of the hook. The
example below shows the order of execution in RSpec:
before(:all) do
puts "Calling before(:all)"
end
before(:each) do
puts " Calling before(:each)"
end
after(:each) do
puts " Calling after(:each)"
end
after(:all) do
puts "Calling after(:all)"
How Automated Testing works 25
end
end
Output
Calling before(:all)
Calling before(:each)
In First Test Case
Calling after(:each)
Calling before(:each)
In Second Test Case
Calling after(:each)
Calling after(:all)
What is the use of execution hooks? Let’s look at the test script below (the test script is in
RWebSpec, an extension of Selenium WebDriver. please examine the structure of test scripts
rather than test statement syntax, for now). There are three login related test cases in a single
test script file.
logout
close_browser
end
end
before(:all) do
open_browser
end
after(:each) do
logout
end
after(:all) do
close_browser
end
end
end
By utilizing RSpec’s before(:all), after(:each) and after(:all) hooks, this version is not
only more concise, more importantly, every test case is now more focused (distinguished
from each other). Using these hooks effectively will make test scripts more readable and
easier to maintain. For readers who are new to RSpec, don’t worry, I will cover it more in
later chapters.
Cucumber
Cucumber, another relatively new BDD framework in Ruby, is gaining popularity rapidly.
To avoid distractions, we will focus on test practices using Selenium-WebDriver + RSpec.
There will be a dedicated chapter on Cucumber towards the end of this book.
For windows users, especially the ones who have difficulty installing gems behind a
corporate proxy, you may simply download and install free pre-packaged RubyShell (based
on Ruby Windows Installer) at http://testwisely.com/testwise/downloads.
Once the installation (takes about 1 minute) is complete, we can run a RSpec test from
command line. you need to have some knowledge on typing commands in console (called
Command on Windows).
To run test cases in a test script file, enter command
Run individual test case in a test script file, supply a line number in chosen test case range.
The command syntax is the same for Mac OS X and Linux platforms.
4. TestWise - Functional Testing IDE
In Chapter 2, we wrote a simple automated test case using TestWise, a functional testing
Integration Development Environment (IDE). Selenium WebDriver test scripts can be
developed in any text-based editors or IDEs. You can safely skip this chapter if you had
decided the tool. Readers, who want to be more productive with TestWise, might find this
chapter useful.
TestWise defines simple conventions for the test project structure, test file naming and page
classes, as you will see later in this chapter. This helps communication among team members
or seeking help externally when necessary.
Simplicity
TestWise is designed from the ground up to suit testers, without compromises often found
in testing tools that are based on programming IDEs (which are designed for programmers).
Every feature in TestWise has one single purpose: a better testing experience.
To make new-to-automation testers more willing to adopt, TestWise is designed to be easy
to install, launch quickly and get you started in minutes.
A test script file may contain one or more test cases which commonly form a logic group.
When developing or debugging (trying to find out what went wrong) a new test case, you can
just run this single test case and leave the web browser at the state when an error occurred
for analyse. And yes, this is the most frequently used method for executing tests.
Rocky’s mouse
Once I worked with a tester nicknamed Rocky who was in his fifties. Despite many doubts,
he fell in love with automated testing quickly. He developed RSI (Repetitive Strain Injury,
a potentially disabling illness caused by prolonged repetitive hand movements) with his
mouse hand. Certainly years of the using computer mice had contributed to that. When
TestWise - Functional Testing IDE 33
we worked together on test cases, I moved the mouse to the far right side and sometimes
even put a piece of paper between him and the mouse. Changing a habit is never easy,
but Rocky was doing admirably well. Weeks later, Rocky used the keyboard more than the
mouse and felt more productive as a result. Months later after I left the project, I met one
of his colleagues, who told me: he saw Rocky once snapped the mouse on his desk, and
said to himself: “Zhimin said not to use it”.
4.5 Snippets
Snippets in TestWise are small bits of text that expand into full test script statements. The use
of snippets helps to create test steps more effectively when crafted manually. For example,
type ‘cl’ then press Tab key in a script editor, TestWise will expand it into the test statement
below (clicking a hyperlink):
4.8 Wrap up
We have quickly introduced some features of TestWise to help you develop test scripts more
efficiently. For more details, please check TestWise online documentation and screencasts.
5. Case Study
In this chapter, we will write six automated tests for a test web site.
• Sign in
• Select flights
• Enter passenger details
• Pay by credit card
We will create four test script files, inside which are test cases that are dedicated to testing
each core function.
I suggest you spend a few minutes playing with this web site to get familiar to it, as you do
for your work.
5.2 Preparation
The automated test framework used in this case study are Selenium WebDriver + RSpec, and
automated tests will be executed in Chrome.
¹http://travel.agileway.net
Case Study 36
Assume there is an existing folder c:\work\agiletravel, we can add a folder ui-tests under it
to store our automated test scripts.
In TestWise, select menu ‘File’ → ‘New Project’ (close the existing project first if there is
one), specify
If you want to open this project in TestWise later, select menu ‘File’ → ‘Open Project’, locate
the project file agiletravel-ui-tests.tpr under c:\work\agiletravel\ui-tests folder.
Case Study 37
Test Design
We start with two simple and common test cases: one positive and one negative
• Sign in OK
• Sign in failed with invalid password
A test case skeleton is created in newly created test script file login_spec.rb:
Set test case name by changing the text “New Test Case” to “User can sign in OK”.
Start Chrome browser, navigate to our test site URL: http://travel.agileway.net, and enable
TestWise Recorder by clicking its icon on the toolbar. In Chrome, enter user name and
password (agileway/testwise), and click ‘Sign in’ button.
A test case is not complete without checks. We could use the presence of the text ‘Welcome
(username)’ as the determination of a user is signed in successfully. To create this assertion
step, highlight “Welcome XXX” text, right click and select ‘Add verifyText for …’.
Case Study 38
Now right click in the recorder window and ‘Copy all’ recorded test steps:
Paste recorded test steps in the test case in TestWise. Now we get:
Run the test (right click any line within the test case and select Run “User can sign in OK”)
Now we continue to add another login related test case in login_spec.rb: user failed to sign
in with invalid password. By using TestWise Recorder, we can quickly create this negative
test case as below:
Now click on the tool bar to run the two test cases in login_spec.rb. The second test case
failed, but it runs fine by itself. Let’s examine. In TestWise, the error occurred on line 23.
Clicking the ‘Test Output’ tab, error trace tells us that the element with id “username” could
not be located:
Case Study 40
To debugging test scripts for Web applications, the number one rule is to keep the browser
open and inspect after test execution. TestWise does this automatically when running one
test case. For running all test cases in a test script file, by default, the test script closes the
browser it started. This is necessary as we don’t want to see many browser windows when
running a suite test scripts. Back to our problem, we can simply (and temporarily) comment
out the test statement of closing browser (in after(:all)).
after(:all) do
# @driver.quit unless debugging?
end
Run the test script (both test cases) again. This time, we see the page showing in the browser
is the one after signing in successfully, as the result of executing the first test case. Our second
test case was expecting the home page to enter a user name in a text box. Well, since the
current page is not the home page, the test failed.
Case Study 41
How can you prevent execution of the first test case from affecting the second one? One
solution is to add a ‘sign off’ step: driver.find_element(:link_text, "Sign off").click at
the end of the first test case.
Both test cases should pass now. Don’t forget to uncomment the line # @driver.quit unless
debugging? to close the browser after the test execution completes.
Case Study 42
it "Return trip" do
driver.find_element(:id, "username").send_keys("agileway")
driver.find_element(:id, "password").send_keys("testwise")
driver.find_element(:name, "commit").click
driver.find_element(:xpath, "//input[@name='tripType' and @value='return']").click
elem_from = driver.find_element(:name, "fromPort")
Selenium::WebDriver::Support::Select.new(elem_from).select_by(:text, "Sydney")
elem_to = driver.find_element(:name, "toPort")
Selenium::WebDriver::Support::Select.new(elem_to).select_by(:text, "New York")
elem_depart_day = driver.find_element(:id, "departDay")
Selenium::WebDriver::Support::Select.new(elem_depart_day).select_by(:text, "02")
elem_depart_month = driver.find_element(:id, "departMonth")
Selenium::WebDriver::Support::Select.new(elem_depart_month).select_by(:text, "May 2016")
elem_return_day = driver.find_element(:id, "returnDay")
Selenium::WebDriver::Support::Select.new(elem_return_day).select_by(:text, "04")
elem_ret_month = driver.find_element(:id, "returnMonth")
Selenium::WebDriver::Support::Select.new(elem_ret_month).select_by(:text, "June 2016")
driver.find_element(:xpath,"//input[@value='Continue']").click
For avoid wrapping in text, I changed long dropdown selection test step like the
one below:
Selenium::WebDriver::Support::Select.new(driver.find_element(:name, "fromPort")).\
select_by(:text, "Sydney")
to
elem_from = driver.find_element(:name, "fromPort")
Selenium::WebDriver::Support::Select.new(elem_from).select_by(:text, "Sydney")
These two versions are equivalent. Personally, I prefer the first one, as I generally
like one test step line for a user operation.
You might notice the step below wasn’t included in the recorded test steps.
driver.find_element(:xpath, "//input[@type='radio' and @name='tripType' and @value='retur\
n']").click
This is because this radio button was already pre-selected. You may skip this step. I added
this step as I want to make sure this radio button is selected. To record this step, you
Case Study 44
Or you could try inspecting the HTML source manually (see ‘Identify Web Controls’ section
in Chapter 3).
You may want to add ‘sign off’ steps to make both the test cases work. But there is another
easier and cleaner way.
You might have noticed that both test cases start with same 3 sign-in test steps and end with
a sign off test step. If we think about it, we don’t have to test the functionality of signing
in and signing off for each test case. In fact, our focus is to test the different scenarios after
signed in.
With the knowledge of RSpec, we can move these 3 test steps into a ‘before(:all)’ execution
hook. This way, we only need to sign in once regardless of how many test cases in this test
script file.
before(:all) do
@driver = Selenium::WebDriver.for(:chrome)
driver.navigate.to(site_url)
driver.find_element(:id, "username").send_keys("agileway")
driver.find_element(:id, "password").send_keys("testwise")
driver.find_element(:name, "commit").click
end
after(:all) do
@driver.quit unless debugging?
end
it "One-way trip" do
driver.find_element(:xpath, "//input[@type='radio' and @name='tripType' and @value='one\
way']").click
# ...
end
it "Return trip" do
driver.find_element(:xpath, "//input[@type='radio' and @name='tripType' and @value='ret\
urn']").click
Case Study 45
# ...
end
If you run the test script file (both test cases), the second test case failed. That’s because
after execution of first test, the browser has gone to the next page: Passenger Page. To
make the second test case (as well the first one) pass, we could use another execution hook:
before(:each).
before(:each) do
# before each test, make sure on flight page
driver.navigate.to "#{site_url}/flights/start"
end
Tip: You could use TestWise Snippets to enter this test step: type dnt then press ‘Tab’ key.
There is no need to use the recorder here, just type in the test step (a good test automa-
tion specialist may use recorders wisely but won’t totally depend on them). The string
"/flights/start" is the relative URL of test site, which you can get by examining the address
showing in a browser.
The HTML fragment <div id="returnTrip"> is the section that will be hidden when the ‘One
way’ radio button is clicked.
Add the assertion to the test script.
it "One-way trip" do
driver.find_element(:xpath, "//input[@name='tripType' and @value='oneway']").click
expect(driver.find_element(:id, "returnTrip").displayed?).to be_falsey
elem_from = driver.find_element(:name, "fromPort")
Selenium::WebDriver::Support::Select.new(elem_from).select_by(:text, "Sydney")
elem_to = driver.find_element(:name, "toPort")
Selenium::WebDriver::Support::Select.new(elem_to).select_by(:text, "New York")
elem_depart_day = driver.find_element(:id, "departDay")
Selenium::WebDriver::Support::Select.new(elem_depart_day).select_by(:text, "02")
elem_depart_month = driver.find_element(:id, "departMonth")
Selenium::WebDriver::Support::Select.new(elem_depart_month).select_by(:text, "May 2016")
driver.find_element(:xpath,"//input[@value='Continue']").click
If the passenger’s details are saved properly, the full name is pre-populated as card holder
name on the credit card page. We could use this as our check, i.e. getting value of text box
with name “holder_name”.
The last assertion step is not from the recorder, you need type it in.
• AJAX Testing
• Retrieving text or value from specific element
Test Design
We navigate our way to the payment page. After filling in the credit card details and clicking
on the ‘Pay now’ button, an animated loading image (see below) shows, indicating that the
payment is being processed.
After a few seconds, the flight book confirmation is displayed containing a booking number
and flight details. The animated loading image disappears.
Case Study 49
I am sure that you are now quite familiar to this kind of user experience - the web page
processes information and shows the results without having to refresh the whole page.
The term used to describe the technology responsible for this enhanced user experience is
‘AJAX’. From the testing perspective, an AJAX operation immediately ‘completes’ after the
mouse/keyboard action (such as clicking the ‘Pay now’ button), no page reload is observed.
After the server finished processing the request, seconds or even minutes later, some part of
web page may be updated.
One simple solution for testing an AJAX operation is to wait enough time for the AJAX
operation to fully complete, then perform assertions like below:
The above approach works, but is not efficient. If the AJAX operation finishes early, the test
execution will still pause there and wait unnecessarily. RWebSpec introduces a convenient
function try_for(seconds) { test steps } to keep trying next test steps every 1 second up to a
specified time. If the operation was performed successfully within the given time, it moves
on to the next test step. If the operation still cannot be performed after that time, an error is
thrown.
Sometimes it may be useful to get a value or text from a specific element on the page. For
example, if the booking number in this website is in some number pattern (such as 20120228-
123), we can further verify the booking number against the pattern.
When developing a test case, we often want to seek confirmation by displaying certain data
(also known as printing out). For instance, a tester may want to print to the console the
confirmation number from the test output. In TestWise, you can use the puts function to
display text in the console window, as shown below:
A more detailed test report can be found under ‘Test Report’ tab.
Case Study 52
5.9 Wrap up
We have created several automated test cases in Selenium WebDriver. Along the way, some
techniques were introduced. After this exercise, you should be ready to write real tests
for your project. I expect that some of you might be very excited, especially after seeing
execution of a couple of real tests for your project, and think that test automation is easy.
Here I want to remind you of the test automation camel . After writing dozens of test scripts,
you will face the first hump: Hard to Maintain. But that’s OK. In Chapter 7 and 8, I will
show you how to overcome that hump!