One of my primary goals for the design of MuseIDE and the support for building Selenium-based tests is to lower the cost of building and maintaining tests built in a visual IDE.
There is a design pattern that test automation engineers use to reduce maintenance cost in coded tests: the Page Objects pattern. The purpose of the pattern is to separate the details of the page implementation (such as how to locate an element on a page) from the logic of the tests. In doing so, and by encapsulating the page implementation details into classes, duplication of those details is greatly reduced…or even eliminated entirely. In turn, this reduces maintenance cost because when those details change, they only need to be updated in one place. It can also reduce the cost of test development by building logic that can be re-used easily in future tests. Here is a more detailed code example of Page Objects in coded tests if you are curious to see what test code may look like.
When you look at the classes built for a Page Objects implementation, you are essentially seeing a model of the application – the pages and the elements, data sources and actions that are contained on each page. You may also notice that the things that are modeled (pages, elements, data sources, actions) will be very similar for each web application tested…even for applications that look very different on the surface. This implies an opportunity to build a general-purpose model and GUI that will serve for many or most applications.
Opportunities for re-use
Lets start by looking at the MuseIDE Selenium test shown below — it performs a few simple steps:
- Start at a URL
- Click a link to the login page
- Login (fill username & password, press login button)
- Verify the login succeeded
- If the logout button is present, press it, wait for completion and check for success
- Close the browser
The login process has been implemented as a reusable function, so that is good. But nearly every other step has details that are likely to be duplicated in other tests that deal with these pages. Some examples
- “Go to…” step has a hard-coded URL. Every test that starts on this page will have a copy…and they would all need to change if that URL changes.
- Each of the click steps contains an element locator, which may be duplicated in other tests.
- Each of the verify steps references a condition on the page, which is duplicated in the login function and may be duplicated in other tests as well.
Convert to use Page Objects
Here is the same test, converted to use the Page Objects extension. You will immediately notice two differences: (1) the test is much more expressive – anyone could read it and immediately understand what each step in test is doing – and (2) all of the nitty-gritty details of the implementation have vanished. You may also notice a 3rd difference – there is a little more hierarchy in the test. The steps are separated into those on the HomePage and those on the LoginPage.
So where did all the details go? They are moved into Web Pages defined in the project. The first, the HomePage, is very simple in this example, so lets look at it first.
The HomePage only has two components defined – the Page URL and one element – the LoginPageLink.
When the Start at Page step executes, it looks up the URL for the page and sends the URL to the browser. Each test that starts at the HomePage no longer duplicates the URL – it is defined in this one place.
One element has been defined on the page – the LoginPageLink. The element locator has been moved here and is referenced by name in the click step of the test.
The LoginPage has many more elements defined, as well an action and a few conditions.
The Perform Action step in the test references an Action on the page. The action simply references a function defined in the project.
The Verify and Wait steps in the test reference conditions on the page. Again, the details have been moved out of the test and into the page model.
Also notice that the conditions do not duplicate the locators for the elements they reference – they use a special notation to reference the element as defined on the page.
The login function was also converted to use Page Objects. Here is the initial version:
And here is the Page Objects version:
Converting the test to model the HomePage and LoginPage in this way has eliminated duplication of the element locators and conditions, as well as making the tests easier to read. When minor changes are made to the application that affect element locators, only the Page Objects will need updates. Each change will be made in just one place – reducing cycle time and lowering costs.
To get MuseIDE, download the installer.
To install the Page Objects extension into your project, press the Extensions… button in the project navigator, switch to the Available tab and press the + button next to the Page Objects extension.