Friday, January 1, 2016

LoadableComponent is AJAX

    In my test automation I have used the LoadableComponent class aiming to make writing PageObjects less painful, like it was suggested by countless articles and their authors. They try to convince you that this will provide a standard way of ensuring that pages are loaded and you can use it to help reduce the amount of boilerplate code in your tests, which in turn make maintaining your tests less tiresome. 

    The truth is that we should consider the other side of the coin as well. This pattern violates at least a couple of principles. First is KISS, in 21st century HTML5 your pages should only keep content, not inline CSS or JS. In our test design this means - WebElement map only. Till now I was sure that  there are two basic ways of using my OOD Models -  smart tests or smart pages. All test flow logic had to be placed in one of them. The real question is - do we have to? 

    Next big thing that bothers me is the Single responsibility. It clearly states that a class should have only one reason to change. Is this the case with the examples (both simple and advanced) we are suggested to follow?

    In my humble opinion SOLID design has two kings, SRP and DIP.  Both OCP and ISP confirm the first one. There are a few other things we should consider when aiming at clean code. Overdesign is one of them. Do we need the complexity of having two (at least) classes instead of one. Keep in mind that PageActions class is also a good candidate for implementation. We need to separate the associated/needed actions per page as well. To simplify our lives, we can make the page validation a part of the Actions class. All this could lead to bulky test code. We need to draw the line here - loadable components are not page objects

    Using LoadableComponent in every website automation, without considering its pros and cons is not a good practice. After all they are just simple objects that encapsulates logic for page loading.  Do we need to have 20 lines classes? And do we need to couple those to the page objects? If your answer is yes, at least try to use Composition over inheritance and avoid the recommended samples like this one for your PageObject model

   public class ProjectPage extends LoadableComponent<ProjectPage> {

    Just avoid the overcomplicated hierarchy when you try to emulate real user experience in your E2E  "walking through pages" scenario features. 

    Having in mind all of the above said - when we should consider LoadableComponent? This solution works well in complex "deep" page hierarchy (like shopping journeys) and with no confident URLs (like SPA). The correct answer is AJAX-rich web sites. If your front end is build on top of any MVC, then maybe using partial URLs navigation is a better choice. Still, you have to keep some tests which will exercise the end-user journeys. One way to manage your page objects and their relations is a Graph. We do need a root role for some of the vertices, but this doesn't limit us to the Trees only.  I prefer to represent the graph with explicit edges at the cost of some additional memory. In fact the LoadableComponents are the Edges we need for our Vertex (page) objects. This way we could traverse our abstract data type representation without complex algorithms, only using node links. First we need to add abstraction to our Models

And Page objects containers don't need much of it. By implementing IPageVertex you can provide your own IWebElement map mechanics. Note that this usage is much like ISerializable in C#.

    Now our Edge implementations look like this

No comments:

Post a Comment