Functional Test Refactoring: Extract Page Function
Many testers are aware of Page Object Model, but often don’t do it because time-consuming and error-prone. This refactoring helps! I have been using it many times every working day since 2006.
This is one of the 6 Functional Test Refactorings (see the introduction here):
Extract Page Function
Introduce Page Object
Rename
I have been using “Extract Page Function” refactorings many times daily when working on automated test scripts, since 2006. A quick and reliable practice transform raw test automation steps into a more readable and maintainable version in Page Object Model design.
In my opinion, “Attach test execution to the existing browser” and this “Extract to Page Function” refactoring are the top 2 reasons and practices for my high productivity (10X+ compared to other senior QA engineers) in developing/maintaining high-quality automated end-to-end (via UI) test scripts.
Table of Contents:
∘ Introduction of Page Object Models
∘ Knowledge Point: Page Object Model makes Automated Test Scripts easier to read and maintain
∘ Demonstration (video)
∘ Motivation
∘ Sample Test Case (before)
∘ Sample Test Case (after refactoring)
∘ Mechanics
∘ Refactoring in TestWise
∘ Expected Result
∘ Test Data
∘ “Extract to Page Function” refactoring in steps
∘ How did it work?
∘ Continue “Extract to Page Function …” Refactoring
∘ Sample Page Class (after)
∘ Benefits
∘ Exercises
∘ Related Refactorings
Introduction of Page Object Models
Page Object Models (POM) is the most well-known design pattern in test automation. Selenium documentation lists POM as the first best practice.
“Page Object is a Design Pattern that has become popular in test automation for enhancing test maintenance and reducing code duplication”. [Selenium Doc]
The POM pattern is not new, it existed a few decades ago, i.e., it has been battle-field tested.
One veteran tester in Canberra messaged me in 2009,
“Just finished reading your book (Practical Web Test Automation) and I like it. I am writing to let you know that I have used the page object pattern in 80s. Glad to see you include in the Maintainable Automated Test Design and the support in TestWise”.
The “Object” in POM comes from Object-Oriented Design. Testers without a programming background, don’t worry, the OO knowledge required for test automation is minor. Check out the 10-Minute Guide to Object-Oriented Programming for Automated Testers.
Knowledge Point: Page Object Model makes Automated Test Scripts easier to read and maintain
Let me illustrate it with an example. What do you think of the test script below:
It is not too bad, some may think. But it is no good, from a maintenance perspective. Suppose, you have 100 test scripts like the above, and the user name textbox’s name is changed from `fromPort
` to `fromCity
` (on the flight page), what will happen? Will you do a global search and replace in 100 test script files, it’s not good, isn’t it?
Now hold that thought. Have a quick look at the design below.
I break the test steps into four sections, each section corresponding to the user operations on a web page:
Home page
- enter a user name
- enter password
- click the sign in buttonFlight page
- Select from city
- Select the destination city
- Click the next buttonPassenger page
- Enter the passenger’s first name
- Enter the passenger’s last name
- Click the next buttonConfirmation page
- Assertion
This design is clearly better. During my training, some manual testers might worry that some level of coding will be involved with implementing this. Yes, there is a bit of coding, but you rarely need to code it, and this often turned out to be the most satisfying part of the training for them. How? That’s what “Extract to Page Function” refactoring comes in, using this in TestWise is fun! They don’t need to code classes or functions, TestWise does these for them.
Demonstration (video)
Motivation
You have long logically grouped test steps
Extract test operations on a web page into a function in a new or existing Page Class.
Sample Test Case (before)
Below are several linear test steps in a test case. I purposely choose some long ones (to make it look complex).
it "User can select one way trip" do
driver.find_element(:xpath, "//input[@value='oneway']").click
Selenium::WebDriver::Support::Select.new(driver.find_element(:name, "fromPort")).select_by(:text, "Sydney")
Selenium::WebDriver::Support::Select.new(driver.find_element(:name, "toPort")).select_by(:text, "New York")
driver.find_element(:xpath, "//input[@value='Continue']").click
expect(page_text).to include("Sydney to New York")
end
Issues with the above test case
Not easy to understand
Hard to maintain
Sample Test Case (after refactoring)
it "User can select one way trip" do
flight_page = FlightPage.new(driver)
flight_page.select_oneway_trip
flight_page.select_from_city("Sydney")
flight_page.enter_to_city("New York")
flight_page.click_continue
expect(page_text).to include("Sydney to New York")
end
It is a lot better, isn’t it?
Mechanics
Identify operations on a web page
Select the first operation on the page
Create a Page Class file, giving a meaningful name
Create a function in the page class with the selected operation
Replace the original test step with a reference to the page class’ operation
Rerun all tests
Refactoring in TestWise
Select the test steps in the test script file
Invoke the refactoring
Enter new or Select existing Page name
Enter a function name
Adjust parameters if necessary (TestWise will analyze the test steps and pre-determine the parameters)
Preview the new function
Apply the refactoring
Expected Result
A new function with the supplied name is inserted in the new/existing Page Class
The test steps in the test case are replaced with a call to the new Page’s function
Test Data
The same test project that helps you do refactoring exercises quickly:
> cd my-working-dir
> git clone https://github.com/testwisely/agiletravel-ui-tests
The test project is at my-working-dir/agiletravel-ui-tests/pre-refactoring
.
“Extract to Page Function” refactoring in steps
Keep reading with a 7-day free trial
Subscribe to The Agile Way to keep reading this post and get 7 days of free access to the full post archives.