1

我正在用 Selenium 和 PhantomJS 试用 CucumberJS。我已经使用这个 StackOverflow 答案作为指南成功地构建了一个 World 对象。

所以现在我正在测试一些基本的步骤定义,但对如何在步骤结束时执行回调有些困惑。这很好用:

module.exports = function () {
  this.World = require("../support/world.js").World;

  this.Given(/^I am visiting Google$/, function (callback) {
    this.driver.get('http://www.google.com')
        .then(function() {
          callback();
        });
  });
};

驱动程序访问 Google.com,直到加载请求的文档后才会触发回调。但是我发现这个语法有点罗嗦,所以我想也许我可以直接传递callbackthen()我的第一个承诺之后,就像这样:

module.exports = function () {
  this.World = require("../support/world.js").World;

  this.Given(/^I am visiting Google$/, function (callback) {
    this.driver.get('http://www.google.com')
        .then(callback);
  });
};

然而,这失败console.log了,似乎callback. 这是输出:

  Scenario: Googling           # features/theGoogle.feature:6
    Given I am visiting Google # features/theGoogle.feature:7
      [object Object]


    (::) failed steps (::)

    [object Object]

这里发生了什么?我期待它callback可以简单地传递给then()函数并在承诺完成后执行。为什么将其包装在匿名函数中使其工作?

4

1 回答 1

1

正在发生的事情是callback使用driver.get().then.

换句话说,这就是发生的事情:

this.driver.get('http://www.google.com')
  .then(function(result) {
    callback(result);
  });

问题是,如果回调以某些东西作为其第一个参数调用,黄瓜的回调将认为失败,因为它应该是一个错误,如callback(new Error('Something went wrong')).

对我来说,这足以完全禁止使用回调。Selenium 是完全面向承诺的,只有当你想让你的生活更轻松时,你才应该信守承诺。这是完美的,因为 cucumber.js 接受返回的承诺而不是回调,所以这是最好的方法:

// Be sure to omit the last parameter of the function, usually "callback"
this.Given(/^I am visiting Google$/, function () {
  return this.driver.get('http://www.google.com');
});

如果 promise 最终被拒绝,则该步骤将失败,或者如果 promise 已完成,则继续执行下一步。但是在这两种情况下,黄瓜都会等待最后一个承诺,所以你需要做的就是总是返回任何一步的最后一个承诺,因为 Selenium 只会在前一个承诺被解决后才解决/拒绝最后一个承诺。一切看起来都好多了不是吗?

于 2016-03-21T14:45:51.510 回答