Pattern for Functional Testing

November 15, 2008 Pivotal Labs

Regular Selenium tests (in Java) might look like:

selenium.open("/login");
selenium.type("id=username", "bob");
selenium.type("id=password", "password");
selenium.click("Login");
selenium.waitForPageToLoad();
selenium.click("My Account");
selenium.waitForPageToLoad();
assertEquals("bob", selenium.getText("//table[2]/tr[3]/td[2]/");

After a few tests, this kind of thing becomes painful to manage. The typical solution is to create a bunch of constants for IDs and Xpaths, but that doesn’t help too much.

Fellow Pivot Mike Grafton came up with a cool pattern for improving on this. The idea is to create a class representing each page of your web app. Each class contains two types of methods: a bunch of action methods (clickMyAccountLink(), typeUsername()), and a bunch of inspection commands (isLoginButtonEnabled(), getLoggedInUsername()).

When an action takes you to a new page, the corresponding action method returns a new class representing that page. When it stays on the same page, the method just returns “this”. This allows methods to be chained to make the tests more readable.

Here’s how that test would look using this new pattern:

MyAccountPage myAccountPage = new LoginPage(selenium)
  .typeUsername("bob")
  .typePassword("password")
  .clickLoginButton()
  .clickMyAccountLink();

assertEquals("bob", myAccountPage.getLoggedInUsername());

The constructor of each page class should validate that it’s on the correct page (waiting if necessary, and perhaps asserting on the page title).

About the Author

Biography

Previous
Volatility: it's not just for sublimation any more
Volatility: it's not just for sublimation any more

Multithreaded programming was a hot topic at RubyConf this year, and a common theme in many talks was the u...

Next
Pivotal Tracker Fluid Icon
Pivotal Tracker Fluid Icon

Here's a hot Fluid icon for Pivotal Tracker. Thanks, Ted! Check out a couple of other icons in this Fli...