7

Martin Fowler favors having no assertions in page objects however is not definitive on the subject:

Advocates of including assertions in page objects say that this helps avoid duplication of assertions in test scripts, makes it easier to provide better error messages, and supports a more TellDontAsk style API.

Advocates of assertion-free page objects say that including assertions mixes the responsibilities of providing access to page data with assertion logic, and leads to a bloated page object.

An assertion library DSL depends on the domain knowledge of the application under test (aka business domain) but the question is whether you attach the TellDontAsk API to the Page Objects or to the test data models.

Example in Protractor to favor no assertions in page objects

But rather in a User test data model

// `julie` could eventually be loaded from a csv or JSON test data file but
// ultimately you end up creating a new instance of a User class or type
var julie = new User({userName: 'julie', fullName: 'Julie Ralph', ...});
julie.login();

User.prototype.login = function(user) {
  var loginPage = new LoginPage(); // you could go with singletons too
  loginPage.get();
  // below could be within loginPage.get to avoid duplication
  expect(loginPage).toBeLoaded();
  loginPage.setUserName(user.userName);
  // below assertion could be within loginPage.setUserName
  expect(loginPage.getUserName()).toEqual(user.userName);
  // and so on...
};

Example in Protractor that favors assertions within page objects

var loginPage = new LoginPage();
loginPage.login(julie);

LoginPage.prototype.login = function(user) {
  var loginPage = this;
  loginPage.get();
  expect(loginPage).toBeLoaded();
  loginPage.setUserName(user.userName);
  expect(loginPage.getUserName()).toEqual(user.userName);
  // and so on...
};

Either way you can still alias or delegate one from the other, i.e.

User.prototype.login = 
  LoginPage.prototype.login.bind(LoginPage.prototype);

Then the test engineers get to choose any of these 2 DSLs:

julie.login();
loginPage.login(julie);

Would like to know experiences of marking this decision and if you have strong positions on this subject.

2 Answers 2

4

Given that there is disagreement, the answers this question attracts will probably gravitate toward sometimes rather than yes/no.

My opinion is that page objects should have assertions in their constructors, so that my code doesn't offer page methods for a page I never reached.

In a made up example, I don't want to return an account page object when I've hit a 404 because I'll eventually hit a NoSuchElementException.

I don't want my debugging journey to begin at:

Where did this element go / did the selector change?

I want to start at:

Why did I get a 404 instead of the account page?

An extension of this model is Selenium's LoadableComponent concept.

As your site under test becomes more application-like and less document-like, the page object model becomes a leakier abstraction (at one extreme, imagine the page object for a single page application).

I mention LoadableComponent because I think they mitigate the "Bloated Page Object" problem, and part of their solution is overriding isLoaded and putting in custom assertions. From the docs:

The LoadableComponent is a base class that aims to make writing PageObjects less painful. It does this by providing a standard way of ensuring that pages are loaded and providing hooks to make debugging the failure of a page to load easier. You can use it to help reduce the amount of boilerplate code in your tests, which in turn make maintaining your tests less tiresome.

1
  • 1
    This is a nice answer, I must disagree though regarding As your site under test becomes more application-like and less document-like, the page object model becomes a leakier abstraction because even on a single page app you'll notice the use of deep linking, you'll also notice how partials can be matched with page object models. As Fowler point out the term Page is the standard but the concept is about modeling panels, widgets, sections of the page. Dec 24, 2014 at 23:17
1

I would say no, don't put assertions in page objects. I prefer

  • a consistent approach using the test framework DSL
  • keeping to simple assertions that are self describing
  • keeping page objects to more defined roles of locators, actions and services (sets of actions)
  • seeing if there are multiple assertions (anit-pattern but common for ui tests) inline

Your Answer

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

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