Initially the Page Object Model, or POM, was introduced as a recommendation to help test automators to build their tests. It suggests a simple structure to avoid early maintenance problems. In a lot of situations this approach will be more than satisfiable. But what if it is not? Is there a valuable alternative to the Page Object Model?
The first reason to consider another model is the fact that Page Object Model makes the tester think in terms of “pages”, rather than in terms of the real behavior of the application. The primary concern of our tests should be the behavior of the application, the secondary concern is the implementation. Let us start by looking at the application from a different perspective:
Actor/Role: The user who is working with the system (Who?)
Goals: The actor is trying to achieve a goal, using the system (Why?)
Tasks: In order to achieve this goal the actor must execute some tasks (What?)
Actions/Interactions: To execute this task, certain interactions with the system are needed (How?)
This point of view will change the way we look at the application and thus how we want to model it. It will take us away from the idea that an application consists of a bunch of pages which interact with each other. Instead, it will give us an actor who plays a given role. In this role, the actor will try to achieve a goal by executing some tasks. Each of these tasks can be achieved by a combination of interactions with the system. Looking at the application from the actor perspective is often used when working in a BDD (Behavior Driven Development) environment. This point of view makes us focus more on the user and their abilities, rather than on the application itself. This way of modelling the application is called the Screenplay Pattern.
Another reason to reconsider the Page Object Model is the fact that it does not follow some of the Object Oriented design principles for good programming. The Page Object Model has a lot of benefits which we explained in the previous automation post, and even though the model helps to make our code more readable, reusable and maintainable, there are some technical challenges. Over time, the code, and thus the tests, can become harder to maintain and in some cases they even become a tangled mess riddled with deep inheritance hierarchies. Automated testing is an engineering skill, it needs to be done with care. If you want to keep maintenance low, you need to apply the same principles as used in software development. Not following some of the Object Oriented design principles is the reason why maintenance can become a pain.
Single Responsibility Principle
One of the problems with the page object model is that these page classes can become very large. In development terms, a class can be considered “large” when it contains more than 60 lines of code. Let’s take a simple login page, representing two input fields and one button, as an example. If you create a page object class for this login page it would require somewhere around 45 lines of code. And this is just a simple page. Consider a more complicated page with dozens of elements, and the amount of code will increase considerably. But why is this a problem?
One of the principles of good programming is the Single Responsibility Principle (SRP). It states that every class should have the responsibility over a single part of the functionality provided by the software. The responsibility should be entirely encapsulated by this class. In other words, a class should handle only one functionality. Classes with one single responsibility are easier to understand, to implement and to maintain, rather than one single class which tries to provide a solution for everything.
Open Closed Principle
Another problem with the POM is that it violates the Open Closed Principle (OCP). This principle states that a class should be open for extension, but closed for modification. It means that it should be possible to extend the behavior of your class by writing a new class without changing the existing, working code. Following the principle will prevent situations in which a change to one of your classes also requires you to adapt all depending classes. Or it will prevent issues with your code, because you forgot to adapt a depending class. In other words, it will reduce maintenance.
Refactoring PageObjects
When we manage to implement both principles in our test automation approach, it will result in more readable code, more maintainable classes and it will prevent unexpected side-effects of changes to your code. It will reduce the risk of us breaking unrelated code when making a necessary change. Let’s give an example and consider a simple todo list application. Applying the Page Object Model to this application will result in the following typical class structure:
As explained, this POM class structure is not complying with the Single Responsibility Principle and the Open Closed Principle. In order to do that we need to alter the class structure as follows:
All of the above classes have only one single responsibility: one class is responsible for the object identifications and all other classes are responsible for a single task. This makes this approach compliant with the SRP. When adding a new behavior, you don’t need to modify existing classes, which complies with the OCP.
It will take a lot more effort to build up such a class structure and it requires a good understanding of Object Oriented Programming to reach the full potential. For simple applications the Page Object Model is still a good approach. But, if your application, and thus the number of tests, starts to grow, the maintenance on these tests will grow as well. When your maintenance overhead is too big, it might be a good time to start refactoring your model and start thinking about the principles we talked about earlier (SRP and OCP). For bigger and more complex applications the Screenplay Pattern might be a better alternative then the popular Page Object Model.
If you want to know more about the screenplay pattern, please read this article from John Ferguson Smart and Antony Marcano. It explains the technical concepts in more detail. It also gives an example of how to implement this pattern and how your tests can look like when using it as an alternative for PageObjects. There are a few interesting videos online about this topic. There is one by Antony Marcano about the disadvantages of the PageObjects, and another one by John Ferguson Smart in which he explains how he used the Screenplay pattern in the Serenity BDD open-source framework (or read the summary article).