10

Background: In the Selenium UI automation we all have been using Page Objects pattern as the "Best Practice" for years. In Page Objects "methods" are tightly coupled to pages instead of generic context free functions. As per my observations, 70-80% Page objects methods code are not directly reusable in other web applications as every page object method is highly specialized to a specific page in a given web application.

We can also gain the same level of abstraction (if not better) by simply defining an objects collection (Object repository) and a set of well-defined actions/utility functions to operate on it.

Then what exactly is the point of using page object pattern where we can use simple functions which can be re-used in different contexts. So, aren't we over coupling things in page objects?

Dilemma: Fundamentally, there is a handful of UI operations that we can perform in any UI automation. When we are defining methods in the context of a page, aren't we creating over specialized "methods" than generalized "context-free functions" ?

Example: The page object method like "click submit_user_button" which is specific to a page and might not be directly re-usable even in same application in other pages!

I strongly think, this is costing us flexibility=>reusability=>maintainability?

6
  • sqa.stackexchange.com/a/17904/8992 Commented Aug 18, 2018 at 23:12
  • I have downvoted for a simple reason. I've found parsing and understanding long sentences hard. Could you perhaps reword your question by making sentences shorter, putting a dot everytime next part of your statement starts?
    – dzieciou
    Commented Aug 21, 2018 at 12:09
  • 1
    I tried to rephrase it in shorter sentences. Commented Aug 21, 2018 at 20:59
  • Thanks. What do you mean by free-flowing well-abstracted functions? Can you given an example? Also, Object Repository seems to origin from QTP but to me it has vague meaning. Can you explain what is stored in Object Repository and give an example? I guess that there are both methods that are specific to certain pages, and methods that can be useful for different pages. Only by looking at examples I would be able to give more specific answer.
    – dzieciou
    Commented Aug 22, 2018 at 12:38
  • By free flowing as the name implies, not tied to specifics like a page.Similarly object repository can be any data structure or format to store including Json, xml etc . Commented Aug 27, 2018 at 11:24

4 Answers 4

8

Isn't that what pageObjects are in essence: A description of the UI elements on a Page and how you can interact with them.

Now when writing tests you often interact with multiple elements in a certain way to achieve a workflow. Now if multiple tests use the same workflow it might make sense to move the combination of workflow-steps also into the pageObjects so other tests can re-use it. I wouldn't start with this, just keep it DRY.

Splitting all the UI elements and its interactions into pages and workflows just make it easier to read, understand how and when to use them.

I really don't get how this is overcomplicating things. Creating abstractions, decoupling and storing this in files of around 100 lines is what programmers do for a living.

When creating pageObjects don't over-engineer them from the start. Keep the YAGNI principles in mind.

What I like about well done page objects is that you decouple the driver of the browser from the tests. The tests interact with the pages, the pages with the driver. The tests don't know the driver. This means you could switch the driver from Selenium to Cypress without changing the tests in theory.

3
  • May be "overcomplicating" is not the right word. I mean 'overcoupling'.Changing it. Commented Aug 18, 2018 at 14:52
  • In large/complex UI based application s, we usually get page objects much larger than 100 lines. Commented Aug 27, 2018 at 11:41
  • Ah you mean those applications that try to put all features into a single screen/page, that is another enginering anti-pattern. I guess classes should ideally be around 100-500 lines. If you have pageObjects that are larger probably you have some sub-classes or you can split the page in areas. Also read:softwareengineering.stackexchange.com/questions/66523/… Commented Aug 27, 2018 at 12:00
3

Page objects work well in smaller sites where there is little to no re-use of fields because the coupling effect isn't significant enough to cause major issues - there will always be challenges finding a balance between readable tests, DRY, YAGNI, and SOLID.

I've found that once the application is large enough it's better to work in terms of input type objects, so that the test code is passing the locator information as well as any data to be entered.

This massively simplified my test code: I have an object to handle edit-type inputs, another for clickable fields (buttons, links, and so forth), another for checkboxes, one for dropdowns, and so forth. This allows my page object to be a single generic object that calls methods like FindAndClick(string id), FindAndEnterText(string id, string text) etc. (Then I data drive the test so that the ids, text etc. are read from a CSV file by the test harness).

3
  • You still should use the "classical" definition of page objects... it becomes way more important as your site and suite becomes larger. You can still have your specific functions to handle specific elements but those would be referenced/used inside your page objects. Page objects provide organization and your element functions provide a DRY way to deal with those elements on the pages. You can (and probably should) have both.
    – JeffC
    Commented Aug 20, 2018 at 13:10
  • 1
    @JeffC - I found that it didn't work very well, because the site I work with has too many places where the only difference is the page an element is on. It becomes entirely too cumbersome to have to define a logoff element one every page except one, or to build an overly complex inheritance structure so that the header elements (which every page object would need to reference) can be accessed from pages.
    – Kate Paulk
    Commented Aug 20, 2018 at 13:33
  • 3
    In that case, build a header panel page object and use it as needed. A page object doesn't have to represent an entire page, just any repeated functionality. You could have a calendar widget page object or a login dialog page object and so on.
    – JeffC
    Commented Aug 20, 2018 at 13:37
2

The term PageObjects has become greatly over-used (including by me).

To reset:

We have element locators.
Sometimes our element locators also have an action (such as click) with them.
Some element locators are at the page level but others can be considered to be at fragment, frame, workflow or domain specific grouping levels

These locators are then basically accessed in two ways - directly at the top layer of the test script, e.g. click user_submit_button or by your custom DSL which might be submit_user_form and then the function submit_user_form itself has the line click user_submit_button and user_submit_button is defined at the next lower, page object, level.

In either case the 2 key roles that the page object serves are:

  • reduce errors due to duplicate definitions of the same element
  • name the object to make it more readable and easier to maintain

You want the code to read more like

click submit_user_button

and not something like

click(find('div.users span#inputform button'))

Yes we are creating quite specific and selective and not general functions here but in this case general functions is simply not the only goal in writing this sort of specific test code. We are making code maintainable, that is the goal. I've seen code that didn't use Page Objects and it gets ugly looking fast.

5
  • As I understand, any specific code is less flexible so less reusable.And any less reusable code is less maintainable. Is n't it? Commented Aug 19, 2018 at 5:05
  • reusability is one attribute of good code, however it has to be balanced against others and for the specific situation allowing for other factors. programming is all about balancing multiple concerns Commented Aug 19, 2018 at 11:04
  • reusability is good when appropriate. However when two objects are different things, giving them unique names is still good. Commented Aug 19, 2018 at 11:09
  • For UI automation maintainability is the primary goal to achieve in code. Functions like 'click submit_user_button' and 'click_order_save_button' in different pages are a maintenance nightmare in the long run. Commented Aug 20, 2018 at 2:46
  • Also these so called page classes don't have any internal state to protect from outer world for mutation .We never change locator definitions during runtime. Commented Aug 20, 2018 at 3:04
2

As it seems to me, Page Objects does not introduce abstraction to the code since when you define a page object you do that for a specific element of the page. I would also not oppose Page Objects to Object Repository since basically object repositories are intended to store page objects.

When I use Page Object pattern, I can see the biggest value in possibility of combination of that architectural pattern with OOP conceptions and instruments that programming language provides.

For example you can define page objects bound to a class and then extend that class by adding other objects / hiding existing objects. This will help you follow the implementation of your application since this is the common practice to reuse UI components in different places of the application and to extend the components capabilities (what you can address with inheritance when use page object) for example depending on what the role a user has.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.