Page Models: An Object Oriented approach to integration tests design

motif

Setting up the problem

Here is a simple scenario:

1. Go to Google
2. Provide a search string
3. Search the web
4. Make sure that some results are returned

In order to automate it, use your favorite test recording tool. Did you say Selenium IDE? Sure, Why not, but there are other tools, even those solely based on Javascript.

The previous scenario was implemented using Selenium IDE. Below you can see the resulting generated Java code (JUnit4):

Mr. Code meet Mr Freddy

freddy

Now, just imagine that for one reason or another, you have 100 different tests that start the same way (go to Google site, search something, assert results are displayed) and then you make an assertion over some specific thing (eg first result, text snippet of first result, etc). No big deal. But what would happen if that for one terrible (and long) second the locator of the search button is changed from “btnG” to “fasterBtnG”? Every and each one of your 100 tests will fail when asserting that the results message is displayed. If you figure out quickly the root cause of the problem, fix is easy but tedious. You have to spend a lot of time updating manually the click button locator. A better design could be coding your own test the following way:

So code duplication is avoided in a per class case. Tests are more readable. Fixes are easier because of that. But if not all your hundred tests are placed in the same class you will have to update “btnG” as many times as classes you have defined. Worst case scenario: 100 times. Ughh.
We would like a solution where code is not duplicated at all.

Proposed final solution

This solution completely decouples the writing of the test themselves from the underlaying access technology. Also, notice the name of the accessor methods. They are tightly coupled with the view. The main idea here is to provide friendly method names that when used to implement an scenario, reading the code aloud will be similar to read aloud a use case:

  • mainPage.setSearch (“Some search string”);
  • mainPage. clickOnSearchButton();

Advantages

  • No access methods are duplicated. So, updating a method will immediately update all the scenarios that use such a method.
  • Access technology (eg Selenium) is completely encapsulated, so if you like/need to change it in the future, you only have to focus on the accessor methods. For example, going from Selenium to WebDriver would be particularly easy.
  • Coded scenarios high re-usability: Accessor logic separated from test logic.
  • Pretty good readability of test code because of accessor methods names being tightly coupled with the actual view. Scenarios could be implemented almost as defined in a use case. A casual reader of the code will read lines like clickOnSave(), setCustomerName(), selectCountryFromCombo(Country.ARGENTINA), etc. This approach has the additional advantage that QA people with basic knowledge of the language can code the scenarios on their own, provided that the back end part (accessor methods) were already implemented.
  • Once accessor methods are defined, an scenario can be coded really fast. Example: An issue is discovered and fixed. You add the scenario to your tests, so the issue is verified for the following release and from that point on, the test case works as regression testing also.

Disadvantages

  • Implementing accessor methods can take a long time. Particularly true if you do not have access to the code base (to add ids as needed) and/or you are working with technologies different from plain JSP (JSF, GWT, etc.) where you have to figure out how to inject the ids that you want instead of allowing the framework to define then at runtime.

2Note: Although the following problem is not related to this approach (in fact, it is far better to deal with it than test recorders), applications based on Ajax can add a “nice” new dimension to the problem. You have to take into account wait times in most of your accessor methods. And no fixed wait times, but something fancier, like wait until such and such elements are visible, text is present, etc.2

Conclusion

time-is-money

Results are really fast to achieve with test recorders. Pretty cool also when used as proof of concept. But when you can measure your test base in tens of tests or more, maintenance becomes rapidly in some chapter of Nighmare in Elm Street. In order to avoid meeting with Mr Freddy, you should decouple the actual accessor logic from your tests, with the additional advantage that with this approach your coded scenarios will be almost self documented in a highly readable way. Using Page Models pattern when designing your Integration Tests will take precious time on the short term, but in the mid/long term you will save a lot of developing time because of them.2


We'd love to hear your opinion on this post

4 Responses to “Page Models: An Object Oriented approach to integration tests design”

  1. I’ve used this general approach and it works well. One minor issue, though — I’ve noticed that waitForPageToLoad can be unreliable. You may wish to wait for an element to be present instead.

    Agree(0)Disagree(0)Comment
  2. Hi Marshall! waitForPageToLoad() is useful if after performing an action the page reloads completely. Problem happens if you are loading parts of it. Then as you said, you should implement some waitForConditionX, being X: element to be present, visible, editable, etc. Particularly true if behind the scenes you have Ajax working for you.

    Agree(0)Disagree(0)Comment
  3. Hey there Nahuel,

    I’ve recently taken up Selenium and came to similar conclusions as you have in regards to an OO approach. I’m curious, since this article was posted about a year ago, if you’ve had any revelations on the subject since posting? Perhaps you’ve scaled down your OO approach, or perhaps you’ve taken it even further. Whatever the case, thanks for posting — wish I could find more opinions on people’s preferred Selenium style.

    Agree(0)Disagree(0)Comment
  4. Hi Matt! No significant revelations since them ;-). In fact,Selenium 2.0 uses the same concept, with a slightly different name (eg. http://seleniumhq.org/docs/06_test_design_considerations.html#page-object-design-pattern). Let’s say your accesor methods are all defined, then, the next challenge is in defining the accessors grouping. If the page you are trying to model is not a basic one, you’ll end having hundreds of lines of code on the same class. Not very good from design standpoint. One possibility to solve this is by taking a more modular approach, like “getMainPage().getStatisticsDashboard().getFlowCount()” so you have the page and also sub-components. Main rule of thumb here: Keep your framework as simple as possible.

    Agree(0)Disagree(0)Comment