19

Given i'm building my angularjs protractor e2e tesing suite leveraging the page objects pattern.

And i separate page object code in different files as much as reasonable.

  1. What would be a good approach to enable page objects inheritance? javascript classic inheritance? Object.create() based inheritance? Other?

  2. Should i keep expectations within the page object? Or favor Martin Fowler optinion by moving them to an assertion library? in which case how exactly would that look like in this javascript-nodejs technology stack?

I've prepared a live jsfiddle playground here so you can try your improvements on.

Or simply paste code within the answer, i'll paste the jsfiddle content below for clarity:

loginPage.js

"use strict";

// A Page Object is a Singleton, so no need to constructors or classic js inheritance,
// please tell me if I'm wrong or what's the utility of creating a (new LoginPage())
// every time a spec need to use this login page.
var loginPage = {
    // Page Object Elements
    userElm: $('.user.loginPage'),

    // Page Object Assertions
    // Martin Fowler [doesn't favor](http://martinfowler.com/bliki/PageObject.html)
    // assertions in page objects, I'm open to suggestions on how to move 
    // the assertions away from the Page Object and see how an assertion library 
    // could like like in protractor.
    assertInputsDisplayed: function() {
        return ('Assertion: this.userElm: '+this.userElm);
    },

    // Page Object Actions
    get: function () {
        return ('navigating to LoginPage with userElm: '+this.userElm);
    }
};

module.exports.loginPage = loginPage;

loginDialog.js

"use strict";

var loginPage = require('./loginPage.js').loginPage;
var helpers = require('./helpers.js');

// Inherit properties from another Page Object
var loginDialog = helpers.extend({}, Object.create(loginPage), {
    // Page Object Elements
    userElm: $('.user.loginDialog'),

    // Page Object Actions
    get: function () {
        return ('navigating to LoginDialog with userElm: '+this.userElm);
    },

    logout: function () {
        return ('logging out of Dialog. user was: '+this.userElm);
    }
});

module.exports.loginDialog = loginDialog;

helpers.js

"use strict";

// some helper to avoid adding an external dependency for now
var extend = function(target) {
    var sources = [].slice.call(arguments, 1);
    sources.forEach(function (source) {
        for (var prop in source) {
            target[prop] = source[prop];
        }
    });
    return target;
};

usage.js

"use strict";

// Mock $() for easy unit testing this on nodejs REPL
global.$ = function(args) { return ('$BUILT '+args); };

var loginPage   = require('./loginPage.js').loginPage;
var loginDialog = require('./loginDialog.js').loginDialog;

console.log(loginPage.userElm);    //=> '$BUILT .user.loginPage'
console.log(loginDialog.userElm);  //=> '$BUILT .user.loginDialog'
console.log(loginPage.get());      //=> 'navigating to LoginPage with userElm: $BUILT .user.loginPage'
console.log(loginDialog.get());    //=> 'navigating to LoginPage with userElm: $BUILT .user.loginDialog'
console.log(loginPage.assertInputsDisplayed());   //=> 'LoginPage assertion: this.userElm: $BUILT .user.loginPage'
console.log(loginDialog.assertInputsDisplayed()); //=> 'LoginPage assertion: this.userElm: $BUILT .user.loginDialog'

//loginPage.logout();   //=> TypeError: Object #<Object> has no method 'logout'
console.log(loginDialog.logout()); //=> 'logging out of Dialog. user was: $BUILT .user.loginDialog'
4

2 回答 2

8

这是我为培训我的一些同事创建好的量角器测试套件而设置的教程的链接。

这一切都是实时的,有一个演示站点,您可以访问、探索等。

https://github.com/Droogans/ProtractorPageObjects

这将为您设置安装、大纲、组织技术等。

如果您有任何问题,请随时留下问题。

于 2014-01-30T21:52:32.427 回答
5

My opinions and how we structure our test...

  • One general page model that holds some methods we expect most pages to use like go() or we have methods for interacting with some common custom elements.

  • 从这个通用页面继承的许多特定于页面的模型。这些模型上的大多数方法都与获取页面上的各种元素或与该页面的 ui 交互有关。这些模型上没有断言方法。

  • 用于与某些更复杂的小部件交互的 UI 模型。类似于页面模型,但它们不绑定到页面。它们与 UI/小部件相关联。这些模型上没有断言方法。

  • 对于常见的和可重用的断言,我们有断言模型利用各种页面模型和 UI 模型的交互方法。它们按页面或 UI 组织。对于不常见且不能真正重用的断言,我们只是将它们放入规范本身。

  • 规格通常按页面组织,尽管我们确实有某些 UI/小部件的规格。

于 2014-01-30T20:34:22.430 回答