使用Chai作为承诺来解决Protractor和Cucumber中的承诺

时间:2015-07-13 18:29:54

标签: javascript angularjs protractor chai cucumberjs

最近一位同事和我在'#34;右边"上发生了一些分歧。使用Protractor和Chai作为Promised实现Cucumber步骤定义的方法。我们的争论来自于对Cucumber背景下的承诺解决方案的准确性的完全缺乏理解。

我们正在针对AngularJS应用程序进行测试,因此解决承诺和异步行为是必要的恶魔。我们遇到的最大问题是强制同步测试行为并让Cucumber等待步骤定义之间的承诺。在某些情况下,我们观察到的情况是,在Webdriver甚至执行它们之前,Cucumber似乎直接通过步骤定义。我们解决这个问题的方法各不相同......

考虑假设情景:

Scenario: When a user logs in, they should see search form
  Given a user exists in the system
  When the user logs into the application
  Then the search form should be displayed

大多数混淆起源于Then步骤。在此示例中,定义应声明页面上存在搜索表单的所有字段,这意味着多次isPresent()检查。

从我能够找到的文档和示例中,我觉得断言应该是这样的:

this.Then(/the search form should be displayed/, function(next) {
    expect(element(by.model('searchTerms')).isPresent()).to.eventually.be.true;
    expect(element(by.model('optionsBox')).isPresent()).to.eventually.be.true;
    expect(element(by.button('Run Search')).isPresent()).to.eventually.be.true.and.notify(next);
});

然而,我的同事认为,为了满足承诺解决方案,你需要用the​​n()链接你的期望:

this.Then(/the search form should be displayed/, function(next) {
    element(by.model('searchTerms')).isPresent().then(function(result) {
        expect(result).to.be.true;

    }).then(function() {
        element(by.model('optionsBox')).isPresent().then(function(result) {
            expect(result).to.be.true;

        }).then(function() {
            element(by.button('Run Search')).isPresent().then(function(result) {
                expect(result).to.be.true;
                next;
            });
        });
    });
});

后者对我来说确实是错的,但我也不知道前者是否正确。我最终理解的方式()是它与then()的工作方式类似,因为它在继续之前等待承诺解析。我希望前一个例子按顺序等待每个expect()调用,然后通过最终的expect()中的notify()调用next()来向黄瓜发送信号继续下一步。

为了增加更多的困惑,我观察到其他同事写下这样的期望:

expect(some_element).to.eventually.be.true.then(function() {
    expect(some_other_element).to.eventually.be.true.then(function() {
        expect(third_element).to.eventually.be.true.then(function() {
            next();
        });
    });
});

所以我认为我提到的问题是:

  • 上述任何一种有点是对吗?
  • 最终()真正做到了什么?它会像then()一样强制同步行为吗?
  • 和(下一个)真的有什么关系?它与在then()中调用next()不同吗?
  • 是否有一个我们尚未找到的最佳做法指南可以更清楚地说明这一点?

非常感谢提前。

1 个答案:

答案 0 :(得分:4)

  • 你的感觉是正确的,你的同事错了(虽然这是一个合理的错误!)。在运行第二个之前,Protractor会自动等待一个WebDriver命令解析。因此,在您的第二个代码块中,element(by.button('Run Search')).isPresent()将在element(by.model('optionsBox')).isPresent()element(by.model('searchTerms')).isPresent()完成后才会解决。
  • eventually解决了承诺。这里有一个解释:https://stackoverflow.com/a/30790425/1432449
  • 我认为这不同于next()
  • 中的then()
  • 我不相信有最佳做法指南。黄瓜不是Protractor团队的核心焦点,对它的支持主要由github上的社区提供。如果您或您认识的人想写一份最佳实践指南,我们(量角器团队)会欢迎PR!