【问题标题】:How to correctly design page objects using theintern testing framework如何使用实习生测试框架正确设计页面对象
【发布时间】:2016-01-25 12:11:03
【问题描述】:

我正在使用theintern 框架创建功能测试。我想使用“页面对象”为我的测试建模,因为我希望代码可重用。

在最初的documentation 中,有一个非常简化的示例,展示了如何使用一种称为“登录”的方法创建页面对象。
在这个例子中,这个方法的所有逻辑都在方法本身内部。

我想创建一个页面对象来表示比登录页面更复杂的页面,并且能够重用页面内的组件来执行不同的操作。

这是我想做的一个例子:

// in tests/support/pages/IndexPage.js
define(function (require) {
  // the page object is created as a constructor
  // so we can provide the remote Command object
  // at runtime
  function IndexPage(remote) {
    this.remote = remote;
  }

  function enterUsername(username) {
    return this.remote
      .findById('login').click().type(username).end();
  }
  function enterPassword(pass) {
    return this.remote
      .findById('password').click().type(pass).end();
  }

  IndexPage.prototype = {
    constructor: IndexPage,

    // the login function accepts username and password
    // and returns a promise that resolves to `true` on
    // success or rejects with an error on failure
    login: function (username, password) {
      return this
        .enterUsername(username)
        .enterPassword(password)
        .findById('loginButton')
        .click()
        .end()
        // then, we verify the success of the action by
        // looking for a login success marker on the page
        .setFindTimeout(5000)
        .findById('loginSuccess')
        .then(function () {
          // if it succeeds, resolve to `true`; otherwise
          // allow the error from whichever previous
          // operation failed to reject the final promise
          return true;
        });
    },

    // …additional page interaction tasks…
  };

  return IndexPage;
});

请注意我是如何创建 enterUsernameenterPassword 方法的。
这是因为我想在同一页面对象的其他测试中重用这些方法。问题是我不能链接这些方法,它不起作用。

可以链接的方法都返回Command 对象,但是当我链接我的方法时,它们没有在Command 方法上定义,所以第一个方法被调用(在我的示例中这是enterUsername ),但随后第二个失败,显然是因为 enterPassword 没有在 Command 对象上定义。

我想知道如何为我的页面对象建模,以便我可以重用页面对象中的部分代码,但仍然具有像这样流畅的语法。

提前致谢:)

【问题讨论】:

    标签: javascript node.js intern


    【解决方案1】:

    最简单的解决方案是将您的方法用作then 回调处理程序,例如:

    function enterName(username) {
        return function () {
            return this.parent.findById('login').click().type(username);
        }
    }
    
    function enterPassword(password) {
        return function () {
            return this.parent.findById('password').click().type(pass).end();
        }
    }
    
    IndexPage.prototype = {
        constructor: IndexPage,
    
        login: function (username, password) {
            return this.remote
                .then(enterUsername(username))
                .then(enterPassword(password))
                .findById('loginButton')
                // ...
        }
    }
    

    【讨论】:

    • 我想跟进这几个问题: - 如图所示对我不起作用,除非我使用 enterName(username).call(this, function(){... 之类的东西,因为 AMD 模块仅包含 IndexPage。在原型上定义这些可以吗? - 为什么实习生文档完全破坏/重新定义原型而不是添加单个属性?我认为这是一种反模式。如有必要,我会将这些添加为我自己的问题。
    • 抱歉,示例中的辅助函数调用不应该使用this,因为它们不在原型上。但是,是的,最好将它们包含在原型中。 Intern 文档描述了一种通过子类化命令来实现页面对象的方法。但是,拥有可以在普通命令链中使用的辅助函数通常最终会比子类化命令更容易实现和更灵活。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-22
    • 2013-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-30
    相关资源
    最近更新 更多