On the PageObject Pattern

Recently I started to think more in depth about the PageObject pattern – at least how some folks called it initially. One problem I noticed in discussion with colleagues and clients is the lack of pattern description for this so called pattern. I decided to explore this problem in more depth, and try to come up with a constructive solution to that problem.

The PageObject Non-Pattern

Two weeks back at EuroPLoP I attended a workshop with a pattern on pattern writing from Tim Wellhausen and Andreas Fießer. They describe that a pattern consists of at least the following elements:

  • Pattern Name
  • Context
  • Problem
  • Forces
  • Solution
  • Consequences

So, I started to search for descriptions from other people on the PageObject pattern. I wasn’t able to find a single one which could fit into this construct.

This is not a problem in itself, but one thing I learned on pattern writing and problem-solving is the lack of understanding the context and problem in which a solution applies. In general focusing just on the solution to the problem you are solving is considered an anti pattern. Even worse, solution-problemer use the solution in order to inflict problems on you.

This matches the usage of the PageObject pattern in ways where it does not really help. Worse than that. The lack of a proper solution also lead some folks to a worst-case implementation of the pattern. Consider for example the following pseudo-implementation of it (EXTEEME CAUTION: bad example ahead!):

Given the Google Search page
When I enter ‘PageObject pattern’ as search words
Then I find a reference to ‘http://www.shino.de/blog’

Clearly: This is not an implementation of the PageObject pattern as I consider it.

But instead of complaining, let’s try to fix that.

The PageObject pattern

Tim Wellhausen and Andreas Fießer recommend to start with the solution. The solution is probably the simplest thing, as you know what to do in order solve some problem. Here’s a first throw:

Solution
Create one class with appropriate methods for each web page or web page area in your overall flow. The methods for the class should reflect the interaction operations for that page on a business level. In addition each class should provide appropriate fields for each element that the user is interacting with.

So, the pattern is about the support code how I call it in my book. I could elaborate now more on the solution describing that PageObjects provide an abstraction layer between the business description of the automated tests (or requirements) and the application that they exercise. I will keep this in mind while continuing the write-up of the pattern.

Let’s continue on to the problem this solution is solving, and extend our description with that.

Problem
Your automated tests need to adapt to changes in the user interfaces easily. Your automated tests may also need to exercise several different user interfaces for different devices like a regular web site on a desktop browser and a mobile version of your page on a mobile browser.

Solution
Create one class with appropriate methods for each web page or web page area in your overall flow. The methods for the class should reflect the interaction operations for that page on a business level. In addition each class should provide appropriate fields for each element that the user is interacting with.

So, the problem is that our automated need to adapt to changes. Note that this is a direct descendant from the lesson that test automation is software development combined with the thought that software is under development until it is abandoned. If you don’t treat test automation as software development, you are abandoning all your test automation efforts right from the start. (Maybe that’s why capture & replay tools fail, bit I divert.)

Let’s see now what happens when we apply the solution: the consequences.

Problem
Your automated tests need to adapt to changes in the user interfaces easily. Your automated tests may also need to exercise several different user interfaces for different devices like a regular web site on a desktop browser and a mobile version of your page on a mobile browser.

Solution
Create one class with appropriate methods for each web page or web page area in your overall flow. The methods for the class should reflect the interaction operations for that page on a business level. In addition each class should provide appropriate fields for each element that the user is interacting with.

Consequences
You can adapt your automated tests to changes in the user interface by changing the related PageObjects. The PageObjects provide a protected variation layer to decouple changes in the application under test from your test data. You can exchange the PageObject hierarchy for each device.

Liabilities
You need to put effort into designing the PageObject hierarchy to reflect the flow through your application. When the flow through your application changes, you need to change the connecting code between the textual representation of your tests and the PageObject hierarchy. The PageObject hierarchy is tightly coupled to how the web pages are designed. If the pages change in format or content, your PageObjects will have to change most likely as well.

I put the positive consequences and negative liabilities into two separate sections to make the trade-off decision for applying this pattern as explicit as I would like to read about it. These reasons might apply for you, or might not. But if you cross this pattern, you might want to be aware of these drawbacks and advantages.

Let’s see the forces next.

Problem
Your automated tests need to adapt to changes in the user interfaces easily.

Forces
Your automated tests may also need to exercise several different user interfaces for different devices like a regular web site on a desktop browser and a mobile version of your page on a mobile browser, but want to use the same test data for both versions.

You can express the different page flows in your test data, but you will couple your test data to the user interface details by then. With every change to the user interface your test data also needs to change.

Solution
Create one class with appropriate methods for each web page or web page area in your overall flow. The methods for the class should reflect the interaction operations for that page on a business level. In addition each class should provide appropriate fields for each element that the user is interacting with.

Consequences
You can adapt your automated tests to changes in the user interface by changing the related PageObjects. The PageObjects provide a protected variation layer to decouple changes in the application under test from your test data. You can exchange the PageObject hierarchy for each device.

Liabilities
You need to put effort into designing the PageObject hierarchy to reflect the flow through your application. When the flow through your application changes, you need to change the connecting code between the textual representation of your tests and the PageObject hierarchy. The PageObject hierarchy is tightly coupled to how the web pages are designed. If the pages change in format or content, your PageObjects will have to change most likely as well.

For each consequence or liability there should be a force. I think I covered both of them with the current description of the forces.

Finally, let’s derive the context for the pattern which keeps the same before and after applying the solution.

Context
You are developing automated tests for a flow between several web pages. Your application supports multiple user interfaces for different devices like a desktop browser and a smaller version for mobile devices like mobile phones. You want to keep on using these tests in the future as your application changes in flow and user interface.

Problem
Your automated tests need to adapt to changes in the user interfaces easily.

Forces
Your automated tests may also need to exercise several different user interfaces for different devices like a regular web site on a desktop browser and a mobile version of your page on a mobile browser, but want to use the same test data for both versions.

You can express the different page flows in your test data, but you will couple your test data to the user interface details by then. With every change to the user interface your test data also needs to change.

Solution
Create one class with appropriate methods for each web page or web page area in your overall flow. The methods for the class should reflect the interaction operations for that page on a business level. In addition each class should provide appropriate fields for each element that the user is interacting with.

Consequences
You can adapt your automated tests to changes in the user interface by changing the related PageObjects. The PageObjects provide a protected variation layer to decouple changes in the application under test from your test data. You can exchange the PageObject hierarchy for each device.

Liabilities
You need to put effort into designing the PageObject hierarchy to reflect the flow through your application. When the flow through your application changes, you need to change the connecting code between the textual representation of your tests and the PageObject hierarchy. The PageObject hierarchy is tightly coupled to how the web pages are designed. If the pages change in format or content, your PageObjects will have to change most likely as well.

Voila. If we add a name to it, we should be done with the first draft.

Some final thoughts. This is a brief try to put the PageObject pattern into a pattern format. It is a first try, incomplete, and needs feedback over several iterations in order to grow. For example I might have put some of the forces into the problem statement. There are possibly even more forces, or more consequences as liabilities or advantages of the implemented solution. Maybe the name is wrong. So, don’t take this as cast in stone.

Instead I hope that I provided a basis for further discussion about the solution-problemer approaches we are faced quite recently. When I automate a single web form like the parking calculator or the triangle test sampler, then I won’t design a hierarchy of PageObjects for that single form. That’s too much effort put into something not worth doing – maybe not worth doing, yet.

  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Twitter
  • LinkedIn
  • Google Bookmarks

3 thoughts on “On the PageObject Pattern”

  1. Your pattern descrption seems to suggest that having multiple devices is the main driver for Page Object. I’ve always considered the duplication in support code when accessing the same ui for different pieces of business logic to be my major motivation. So, which is it in your opinion?

    1. Oh, as I mentioned I haven’t thought this pattern through completely, and therefore it will surely need additions. I barely use the PageObject pattern, as I don’t know which problem it solves. This is a first try to get this clear for me. In general I keep myself from designing a larger page object hierarchy, and have it grow instead – intentionally refactoring my design to page objects if I see a problem to my current approach.

  2. Its certainly a good first go at formally documenting the PageObject pattern.
    A thought for the next version, The pattern can be used with more than just web pages. I’ve used it with GUI tests using SWTBot.

Leave a Reply

Your email address will not be published. Required fields are marked *