2016-08-03 96 views
4

我碰到了量角器的页面对象的不同类型的语法,我在想,他们的背景是什么,建议采用哪种方式。什么是页面对象的正确的量角器语法?

这是来自Protractor教程的官方PageObject语法。我喜欢它最,因为它是清晰可辨:

use strict; 

var AngularHomepage = function() { 
    var nameInput = element(by.model('yourName')); 
    var greeting = element(by.binding('yourName')); 

    this.get = function() { 
    browser.get('http://www.angularjs.org'); 
    }; 

    this.setName = function(name) { 
    nameInput.sendKeys(name); 
    }; 

    this.getGreeting = function() { 
    return greeting.getText(); 
    }; 
}; 
module.exports = AngularHomepage; 

不过,我也发现了这个类型:

'use strict'; 

var AngularPage = function() { 
    browser.get('http://www.angularjs.org'); 
}; 

    AngularPage.prototype = Object.create({}, { 
     todoText: { get: function()  { return element(by.model('todoText'));    }}, 
     addButton: { get: function()  { return element(by.css('[value="add"]'));   }}, 
     yourName: { get: function()  { return element(by.model('yourName'));    }}, 
     greeting: { get: function()  { return element(by.binding('yourName')).getText(); }}, 
     todoList: { get: function()  { return element.all(by.repeater('todo in todos')); }}, 
     typeName: { value: function (keys) { return this.yourName.sendKeys(keys);    }} , 
     todoAt: { value: function (idx) { return this.todoList.get(idx).getText();   }}, 
     addTodo: { value: function (todo) { 
     this.todoText.sendKeys(todo); 
     this.addButton.click(); 
     }} 
    }); 

    module.exports = AngularPage; 

什么利弊/这两种方法的缺点(除了可读性)?第二个是最新的吗?我已经看到WebdriverIO使用这种格式。

我也从Gitter的一个家伙那里听说,第一个入口是低效的。有人可以向我解释为什么?

回答

5

页对象模型框架变成了主要是因为流行:

  1. 更少的代码复制
  2. 易于维护长期
  3. 高可读性

所以,一般我们根据测试范围和需求开发测试框架(pom),以便于我们使用翼适合的框架(POM)模式。没有这样的规则说,我们应严格遵循任何框架。

:框架是,使我们的工作轻松,以结果为导向,有效

在你的情况,一日一个看起来不错,方便。在维护阶段它不会导致混淆或冲突。

示例第一种情况 - >元素定位器的声明发生在每个页面的顶部。如果将来任何元素定位器发生更改,将很容易进行更改。

第二种情况,在块级别声明的定位符(分散在整个页面上)。如果将来需要,这将是一个耗时的过程来识别和更改定位器。

因此,根据以上几点选择您感到舒服的人。

+0

非常感谢,这是有道理的:) – anks

+0

@anks,如果您觉得,我的文章帮助您并更正,请勾选正确。 –

3

我更喜欢使用ES6类语法(http://es6-features.org/#ClassDefinition)。在这里,我准备了一些简单的示例,我如何使用ES6类和一些有用的技巧来处理页面对象。

var Page = require('../Page') 
var Fragment = require('../Fragment') 

class LoginPage extends Page { 
    constructor() { 
     super('/login'); 
     this.emailField = $('input.email'); 
     this.passwordField = $('input.password'); 
     this.submitButton = $('button.login'); 

     this.restorePasswordButton = $('button.restore'); 
    } 

    login(username, password) { 
     this.email.sendKeys(username); 
     this.passwordField.sendKeys(password); 
     this.submit.click(); 
    } 

    restorePassword(email) { 
     this.restorePasswordButton.click(); 
     new RestorePasswordModalWindow().submitEmail(email); 
    } 
} 

class RestorePasswordModalWindow extends Fragment { 
    constructor() { 
     //Passing element that will be used as this.fragment; 
     super($('div.modal')); 
    } 

    submitEmail(email) { 
     //This how you can use methods from super class, just example - it is not perfect. 
     this.waitUntilAppear(2000, 'Popup should appear before manipulating'); 
     //I love to use fragments, because they provides small and reusable parts of page. 
     this.fragment.$('input.email').sendKeys(email); 
     this.fragment.$('button.submit')click(); 
     this.waitUntilDisappear(2000, 'Popup should disappear before manipulating'); 
    } 
} 
module.exports = LoginPage; 

// Page.js 
class Page { 
    constructor(url){ 
     //this will be part of page to add to base URL. 
     this.url = url; 
    } 

    open() { 
     //getting baseURL from params object in config. 
     browser.get(browser.params.baseURL + this.url); 
     return this; // this will allow chaining methods. 
    } 
} 
module.exports = Page; 

// Fragment.js 
class Fragment { 
    constructor(fragment) { 
     this.fragment = fragment; 
    } 

    //Example of some general methods for all fragments. Notice that default method parameters will work only in node.js 6.x 
    waitUntilAppear(timeout=5000, message) { 
     browser.wait(this.EC.visibilityOf(this.fragment), timeout, message); 
    } 

    waitUntilDisappear(timeout=5000, message) { 
     browser.wait(this.EC.invisibilityOf(this.fragment), timeout, message); 
    } 
} 
module.exports = Fragment; 

// Then in your test: 
let loginPage = new LoginPage().open(); //chaining in action - getting LoginPage instance in return. 
loginPage.restorePassword('[email protected]'); // all logic is hidden in Fragment object 
loginPage.login('[email protected]') 
+0

我发布这个之后,我的朋友还建议我使用ES6,我同意它看起来非常好,更熟悉我(我已经在Ruby中写过页面对象)。 虽然有一个问题 - 你不使用量角器的元素语法(比如'element(by)。css('someclass')') - 是因为$('')更短还是其他原因? – anks

+0

是的,我使用元素(by.css(''))很多,而$/$$是很好的全局快捷方式。没有任何功能差异。 – Xotabu4

相关问题