Dont Use Object Repositories with Selenium WebDriver

Selenium WebDriver is rather new in the test automation world.

Before Selenium, all attention and spotlight belonged to a product called QTP (UFT is the new name), built by Mercury Interactive (owned now by HP).

Everyone was talking about QTP and Mercury so much that the Selenium creator, Jason Huggings, named his new automation tool after another chemical element, Selenium.

How does QTP work?

QTP allows automation tests to be created for a variety of application types in 2 different ways:

  1. through record-and-play
  2. through code

When using the record-and-play mode, the user goes through the following steps to record a new test:

  1. opens the QTP application
  2. selects the record button
  3. selects the application to be tested
  4. starts the recording
  5. goes through the application like a normal user
  6. stops the recording

After the recording is stopped, a new automated test is created.

The automated test can be played back.

Its code uses items from an object repository that is created during the recording process:

The object repository is a tree-like structure that has a node for each application element used during recording.

Each node has in the object repository multiple attributes:

  1. name
  2. class
  3. type
  4. locator
  5. value

So the automation code works by interacting with application elements found in the object repository.

This seems a decent approach. Why not use it with Selenium WebDriver as well?

Test automation with Selenium WebDriver is done 100% through code.

There is a tool called Selenium IDE that relies on record-and-play but it is useless for serious test automation due to numerous limitations.

Test automation with Selenium WebDriver does not rely at all on record-and-play.

And object repository is a record-and-play concept.

Without recording the test, how would the object repository be created?

Does this mean though that the object repository cannot be used with Selenium automation?

Lets see how code looks when using an object repository.

We have a Home Page class that implements the user interaction with a typical Home Page such as the Hudson Bay’s one

The object repository for the page could be a property file (or xml, csv, yaml) as follows:

BRANDS = brands.id
WOMEN = women.id
SHOES = shoes.id
HANDBAGS = handbags.id
ACCESSORIES = accessories.id
BLACK_FRIDAY_SALE = blackfridaysale.id
BLACK_FRIDAY_DEAL = blackfridaydeal.id

The HomePage.java page object class uses the element ids from the object repository:


public
class HomePage {
  private WebDriver driver;
  private PropertyFile props;
  private final String URL = “http://www.thebay.com";
  public HomePage (WebDriver driver) {
     this.driver = driver;
     this.props = new PropertyFile(“homePage.properties”);
  }
  public void open() {
    driver.get(URL);
  }
  public BrandsPage goToBrands() {
   By brandsId = By.id(props.(“BRANDS”));
   WebElement brands= driver.findElement(brandsId);
   brands.click();   
   return new BrandsPage(this.driver);   
  }
   public WomenApparelPage goToWomenApparel() {
     By womenId = By.id(props.get(“WOMEN”));
     WebElement women= driver.findElement(womenId);
     women.click();
     return new WomenApparelPage(this.driver);
  }
  .......................
}

I added only 2 methods to the class for the first 2 top menu options, Brands and Women.

Each method gets the menu option’s locator through an object of the PropertyFile class.

This class opens the property file, searches for a property name, gets the property value and returns it:

package Property;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Properties;
public class PropertyFile {

private final Properties properties;

public PropertyFile(String fileName)
{
try {
properties = new Properties();
File file = new File(fileName);
InputStream input = new FileInputStream(file);
properties.load(input);
}
catch (Exception exception) {
throw new RuntimeException ("cannot load the property file");
}
}

public String get(String name) {
try {
return properties.getProperty(name);
}
catch(Exception exception) {
throw new RuntimeException ("cannot find "+ name);
}
}
}

What are the “advantages” of using an object repository?

  1. All locators for the elements of a page are in 1 place
  2. Since the page classes dont have locator variables, they are shorter.

You noticed, of course, that there are double quotes around advantages.

They are actually disadvantages.

What are the disadvantages of an object repository?

  1. It is very difficult to read or change the value of an element locator

An ecommerce site has more than 50 pages, each with hundreds of elements.

We will have then an object repository for each page.

While working with code, there are many times when we need to either read or change the value of a locator.

Usually, this is done in the IDE (Eclipse, Intellij) by pressing the F3 key or selecting Open Declaration for the locator variable:

This does not work with object repositories since a locator is just a line in a text file.

To read or change the locator value, you have to

  • find the object repository for the page
  • open it
  • search for the element name in the file

That’s a lot of work for just reading a locator value.


2. A page object class becomes a method container if it has no locator variables.

Page object classes are classes.

A JAVA class has variables for state and methods for behavior.

The methods operate on the variables of the class:

Encapsulation (computer programming)
From Wikipedia, the free encyclopedia
In programming languages, encapsulation is used to refer to one of two related but distinct notions, and sometimes to the combination thereof:
- A language mechanism for restricting direct access to some of the object’s components.
- A language construct that facilitates the bundling of data with the methods (or other functions) operating on that data.

Removing the locator variables from a page object class means violating the encapsulation principle since

  • the class does not have variables any longer
  • its methods do not operate on the class variables

3. Using object repositories does not scale well for big page object classes

The HomePage class for the HudsonBay site will be big, with lots of locators and lots of methods.

Having big classes with more than 200 lines of code and more than 10 methods is a bad practice.

So they should be broken down in smaller classes.

We could do this for the HomePage by creating classes for the HomePage widgets:

  • top menu widget
  • sales and deals widget
  • header (sign in, my account, gift cards, gift registry, etc)
  • search
  • best sellers
  • black friday deals
  • sponsored products
  • footer

Using page element classes for all widgets will simplify the Home Page class significantly and allow us to keep it small.

But how do we do this with object repositories?

Use the HomePage repository for all page element classes?

Or create an object repository for each page widget?


4. Object repositories do not work well with the Page Factory pattern

This should be no surprise since Page Factory declares together web elements and their locators:

public class HomePage {
private WebDriver driver;
private final String URL = “http://www.thebay.com";

@FindBy(how = How.ID, using = "brands.id")
private WebElement brands;
@FindBy(how = How.ID, using = "women.id")
private WebElement women;

public HomePage (WebDriver driver) {
  this.driver = driver;
}
public void open() {
  driver.get(URL);
}
public BrandsPage goToBrands() {
   brands.click();
   return new BrandsPage(this.driver);
}
public WomenApparelPage goToWomenApparel() {
  women.click();
  return new WomenApparelPage(this.driver);
}
.......................
}

Why are people still suggesting using object repositories with Selenium WebDriver?

One reason may be that many testers learned Selenium WebDriver after working with QTP for a long time.

How QTP works became so familiar to them that they use QTP concepts everywhere.

Another reason may be that it is far easier to write procedural code (as in VB, VB SCRIPT) than object oriented code (as in JAVA or C#).


This article is inspired from a chapter of my new book on improving Selenium code with page object models.

You can find it on Amazon . com at

Improve Selenium Code with Automation Patterns: Page Object Model Page Factory Page Elements Base Page Loadable Component