Page Objects? Pattern Objects.

A common pattern used when writing UI test automation is to use a page object. Page objects contain references to all the elements that are on a certain page. This makes it easier to keep your code organized, and prevents us from having to pepper duplicate references all over the place, which creates a maintenance nightmare.

Sometimes the best time to improve is when things are working fine. Although page objects are good, they do have some limitations. Today I want to talk about an idea that can get past these shortcomings, while allowing for lighter maintenance, and faster test construction. Pattern Objects. 

Scalability

When you have a small project, you’ll have a small number of page objects. But as projects get more complex, the number of page objects increases.

What if you only needed one?

Naming Convention

Unless there’s a good naming convention for your page objects, it’ll be difficult to figure out which one you’re supposed to use when it’s time to write a new test. Or, there’s a risk of duplicating work when you think one’s not been made, and there actually was.

What if there was no guesswork involved? 

Jiggly Elements

Maintaining the locators in a page object can be a lot of work, especially early on, when elements are moving around all over the place. They continue to be

What if you were almost immune to locator fluctuations? 

How Pattern Objects Work

Mainly, they work be using information that’s on the page already, and consistency offered by tools used by UI developers.

Let’s say an application has this form, containing a variety of textfields, select lists, date pickers, buttons and checkboxes:

advanced-form

Here’s what some of the corresponding HTML might look like: example html

(and whoops I just noticed the “active” checkbox has the wrong label on it. Should be “Active” not “Name”. My bad.)

Notice that each element listed has a unique id (which is good!). We could easily write a page object that looks like this:

class CustomerRecordPage {
   elements = {
      "name" => "//input[@id='name']",
      "email" => "//input[@id='email']",
      "investment" => "//select[@id='investment']",
      "dateJoined" => "//input[@id='dateJoined']",
      "active" => "//input[@id='active']",
   }
}

But, notice also that there’s a pattern to the elements:

  • Each element is wrapped in a <div>
  • Each one also has a <label> describing what the field’s for

So instead of a full page object, we could instead build a object for holding these patterns, like this:

class PatternObject {
   patterns = {
      "text_field" => "//div/label[text()='@@']/following-sibling::input",
      "select_list" => "//div/label[text()='@@']/following-sibling::select_list"
   }
}

Once you pick what kind of element you’re targeting, replace the “@@” characters with the name of the label on the screen, and you have your locator:

def enter_text(label, text)
   locator = PatternObject::patterns["text_field"].gsub("@@", label)
   $browser.text_field(:xpath => locator).when_present.set(text)
end

Why This Method?

With the UI tools that developers use to write the applications, it introduces a lot more consistency. that consistency can be used to our benefit. Instead of having a custom locator for every element, we can have a generic locator for every kind of element.

When we can interact with elements in a more generic fashion, it helps simplify the automation. In the example above, every time we want to enter data into a text field, we can do so based on text that’s right on the screen.

When we can specify our tests based on what’s on the screen, we decrease the amount of tribal knowledge and technical debt we introduce into the automation–both things that slow down our efforts.

And, when our automation is written more plainly, more people can understand what it’s doing, what’s being tested and can more easily maintain it.

It cuts down on how many chunks of code have to be maintained. Instead of one page object for each page, we can have one pattern object which probably would apply across all pages–as long as the app is consistent.

If you look closely, you might see some patterns emerge in the applications you automate tests for. What ones can you find? How can you take advantage of them, and free up time spent creating, maintaining and debugging your automation code? 

Advertisements

3 thoughts on “Page Objects? Pattern Objects.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s