Introduction

In the last post, we applied design techniques to refactor the test class and the underlying code design.

Read it here

In this final guide, we will look at how to refactor a page object in response to changes from the business.

When you finish reading, you will be able to create effective page objects for any UI interface you encounter using design principles.

Prerequisites

Before you begin this guide you’ll need the following:

Let’s do it 💪💪💪

The Current Test:

test class

New Requirement:

There are two Test cases now.

We should write them out again so it is clear

Testcase 1: User can start search from Home page

  • Be on the Home page
  • Type Selenium Java in the searchbox
  • click the first suggestion from auto-suggest dropdown
  • Assert results are displayed on the search page.

Testcase 2: User can start search from results page

  • Be on the Search results page
  • Type Selenium Java in the searchbox
  • click the first suggestion from auto-suggest dropdown
  • Assert results are displayed on the search page.

Step 1 — Add the new test case

What has changed?

  • We added two new methods openHomePage() & openSearchPage() to the search engine object, to make sure the test starts from the right page.

  • We changed the test name, assertion and the message returned on failure.

  • We removed all references to WebDriver from the test class.

  • NOTHING ELSE! That’s right. Nothing else needed to change in the test class, because we have written a resilient class.

Step 2 — Let’s update the interface with the 2 new methods

Step 3 - Let’s implement the new methods in the GoogleSearchEngine Class.

Step 4 - Let’s refactor the searchFor method in the GoogleSearchEngine Class.

Looking at current implementation below:

  • We notice the method began from the GoogleHomePage, entered SearchText via the HomePage and results is also coming from the homepage.

In a nutshell, the implementation of searchFor() couples it to the GoogleHomePage making it hard to cater for the new requirement.

What do we do?

1. Decouple SearchFor implementation from GoogleHomePage

  • Find the common element between Homepage & Result page

Home Page

Results Page

You will notice the searchForm is common across all Google Pages. Thus, making it a candidate to extract from the Homepage and move to its own class with the search behaviours.

SearchForm

  • Refactor searchFor() to use the searchForm in the GoogleSearchEngine class.

  • Add a Search Results page to extract results into Domain class SearchResults.

  • This page will extract the link & linkText values from the WebElement List
  • This populates the SearchResults domain object.

Now are back to the where we started.

The test class! But this time, we have refactored all the framework code. The test should work perfectly.

What have we done so far?

  • Refactored the test class add new test case and remove framework code like WebDriver.

  • Refactored GoogleSearchEngine#searchFor method to not depend on GoogleHomePage

  • Added Navigation methods to the SearchEngine Interface.

  • Created SearchForm component to handle all search related task.

  • Created SearchResultPage to collect result.

Conclusion

This completes the three part Page Object series 🥳.

Now go forth and use the lessons from this article to build page objects for your projects.

Things to Note

For brevity the classes were edited to focus on the relevant details, but don’t worry you can find the complete code in my Github repo.

https://github.com/bongosway/selenium-starter

I am happy to answer questions you may have, reach me on any of my handles.