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).
Ouch. This is crying for webrat.
November 14, 2008 at 8:59 pm
It needs a cool name! Like “Functional Mirror Pattern”
November 14, 2008 at 9:29 pm
@luke: the syntax may be nice, but webrat doesn’t solve the same problem as selenium. We tend to rely on selenium because we want to prove that it works given (or in spite of) the browser’s interpretation of the html/js. Often this really matters, especially if your site has any dom-modding js.
November 14, 2008 at 10:03 pm
@Russ I’ve always heard this called the Logical Functional Model:
* http://blogs.msdn.com/micahel/archive/2005/07/27/TheLfmApplied.aspx
* http://blogs.msdn.com/micahel/archive/2005/06/22/UseYourUsersViewpoint.aspx
November 14, 2008 at 10:59 pm
@Wes Sadly, “Logical Functional Model” has a ring to it like a lead bell.
November 15, 2008 at 2:29 am
See also: http://code.google.com/p/webdriver/wiki/PageObjects
November 15, 2008 at 4:55 am
As Luke mentioned this is a perfect use case of Webrat. In fact as of a month or so back you can leverage Webrat to drive Selenium.
At weplay we have Cucumber features which drive our integration tests via Webrat & Selenium and it works great.
Reference: http://github.com/brynary/webrat/tree/master/lib/webrat/selenium/selenium_session.rb
November 15, 2008 at 7:31 am
Josh & Luke: This pattern could definitely be applied to webrat or any other similar tool. My example was in Java and Selenium because that’s where I’ve used this pattern the most. Recently in fact we used this pattern to control an Adobe AIR app.
November 15, 2008 at 4:43 pm
Functional debugging of application specific integrated circuits (ASICs) has been recognized as a very labor-intensive and expensive process. It often dominates the time and cost of the ASIC system development.Functional specification of the design is logically partitioned into linear and nonlinear components. This is is one of those practices that has not caught on as much as other technical practices in the Agile community.Thanks for the update!!
March 20, 2009 at 5:44 am