Monday, August 01, 2011

The Problem with PageObjects, why PageParts are needed

Over the past year or so, several big dogs in the automated web testing community have been pushing hard with the concept of PageObjects. This is a great thing. As such we now have at least two different page object frameworks to use with Watir-Webdriver thanks to the efforts of Alister Scott and Cheezy.

However, the page object frameworks have placed an item on the backburner. I'm not sure why it is, but the concept of repeating items inside of a page has been ignored at this point. Let's say you have a website like Google Finance. The list of news items is a great example of a what I'm calling a PagePart.

PageParts are items that repeat themselves on a page in terms of content types. They repeat with different content depending upon the user who is logged in, but they all look the same semantically. Here's what a Google Finance News item looks like:



There are four of these items wrapped in a div with market-news-stream as it's id.

Without PageParts you might do this:



So how do we identify these items in the tests? When I first started tackling this sort of problem on my current project I had pass through methods inside my PageObject that went to a simple PagePart. This worked, but didn't give me the cool features of the PageObject frameworks, and wasn't that the whole point of adopting the framework?




Wow, this is more complex than not using page parts.

So, how exactly is this better? It's better when you convert your page parts to use the PageObject framework. Caveat, I do not know how you would do this in Cheezy's PageObjects gem, but it works just fine in the watir-page-helper gem:



Every PagePart extends the BasePart. You'll select your container div in your PagePart object using the part_div method. Obviously this could be any HTML element, but it's most likely to be a div. Since the BasePart will redefine @browser with the div, we'll be able to use the cool shorthand, rather than define every method we might need:



The example may seem a bit contrived, but, maybe you're not working with an interface as clean as Google Finance. If you are, you might get some benefit out of using PageParts.

3 comments:

KinoFrost said...

Parts are covered, in part, in the page objects talk from the Watir Day 2011 conference: http://wiki.openqa.org/display/WTR/Page+Objects

I use "parts" as you describe them (I call them interface representations) in my code also, and it's a great time saver and helps with maintainability.

Cheezy said...

I simply use modules for page parts and include them in all of the pages that use them. For example, If we have a page that has a header with a search text field I'd have this:

module PageHeader
include PageObject

text_field(:header_search, :id => 'header_search')
... # other things on the header
end


In all of the pages that use this header I'd include it like this:

page SomePage
include PageObject
include PageHeader

...
end

I also find that it is typical for an application to have a consistent way of displaying error messages whether it be in a styled div or something else. I typically also extract this type of item into its' own module and include it in the pages.

This simple approach allows me to keep my scripts DRY and absorb change more easily.

Cheezy said...

The formatting for my last post was messed up so I decided to create a gist. Here it is - https://gist.github.com/1240538

ShareThis