简体   繁体   English

使用Chai作为承诺来实现量角器和黄瓜中的承诺

[英]Resolving promises in Protractor and Cucumber using Chai as Promised

Lately a colleague and I have had some disagreements on the "right" way to implement Cucumber step definitions using Protractor and Chai as Promised. 最近,我和一位同事在使用Protractor和Chai作为Promised来实现黄瓜步骤定义的“正确”方法上存在一些分歧。 Our contention comes from a mutual lack of understanding of precisely what is going with promise resolution in the context of Cucumber. 我们的争论源于相互之间缺乏对Cucumber环境中诺言解决方案的确切了解。

We're testing against an AngularJS application, so resolving promises and asynchronous behavior is a necessary evil. 我们正在针对AngularJS应用进行测试,因此解决承诺和异步行为是必不可少的。 The biggest problem we've had is forcing synchronous test behavior and getting Cucumber to wait on promises between step definitions. 我们遇到的最大问题是强制同步测试行为,并使Cucumber等待步骤定义之间的承诺。 In some cases, we've observed situations such that Cucumber seems to plow straight through step definitions before Webdriver even executes them. 在某些情况下,我们已经观察到Cucumber似乎在Webdriver甚至没有执行它们之前就直接浏览步骤定义。 Our solutions to this problem vary... 我们针对这个问题的解决方案各不相同...

Consider the hypothetical scenario: 考虑假设的情况:

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

Most of the confusion originates in the Then step. 大多数混乱源自“然后”步骤。 In this example the definition should assert that all fields for the search form exist on the page, meaning multiple isPresent() checks. 在此示例中,定义应断言搜索表单的所有字段都在页面上,这意味着要进行多次isPresent()检查。

From the documentation and examples I was able to find, I felt the assertion should look something like this: 从我可以找到的文档和示例中,我认为断言应该看起来像这样:

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);
});

However, my colleague contends that in order to satisfy promise resolution, you need to chain your expects with then() like this: 但是,我的同事争辩说,为了满足承诺解决方案,您需要使用then()链接期望,如下所示:

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;
            });
        });
    });
});

The latter feels really wrong to me, but I don't really know if the former is correct either. 后者对我来说真的很不对劲,但是我真的不知道前者是否正确。 The way I understand eventually() is that it works similarly to then(), in that it waits for the promise to resolve before moving on. 我对finally()的理解是,它的工作方式与then()类似,因为它在继续执行之前要等待诺言解决。 I would expect the former example to wait on each expect() call in order, and then call next() through notify() in the final expect() to signal to cucumber to move on to the next step. 我希望前面的示例按顺序等待每个Expect()调用,然后在最终的Expect()中通过notify()调用next(),以发出信号通知黄瓜继续进行下一步。

To add even more confusion, I've observed other colleagues write their expects like this: 更令人困惑的是,我观察到其他同事这样写他们的期望:

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();
        });
    });
});

So the questions I think I'm alluding to are: 所以我想提到的问题是:

  • Is any of the above even kinda right? 以上任何一种还算对吗?
  • What does eventually() really do? 最终()实际上是做什么的? Does it force synchronous behavior like then()? 是否会强制执行then()之类的同步行为?
  • What does and.notify(next) really do? and.notify(next)真正做什么? Is it different from calling next() inside of a then()? 与在then()内部调用next()有什么不同?
  • Is there a best practices guide out there that we haven't found yet that gives more clarity on any of this? 有没有我们尚未找到的最佳实践指南,可以使其中的任何内容更加清晰?

Many thanks in advance. 提前谢谢了。

  • Your feeling was correct, your colleague was wrong (though it was a reasonable mistake!). 您的感觉是正确的,您的同事是错误的(尽管这是一个合理的错误!)。 Protractor automatically waits for one WebDriver command to resolve before running a second. 量角器自动等待一个WebDriver命令解析,然后再运行第二个。 So in your second code block, element(by.button('Run Search')).isPresent() will not resolve until both element(by.model('optionsBox')).isPresent() and element(by.model('searchTerms')).isPresent() are done. 因此,在你的第二个代码块, element(by.button('Run Search')).isPresent()将不能解决直到两个element(by.model('optionsBox')).isPresent()element(by.model('searchTerms')).isPresent()完成。
  • eventually resolves promises. eventually兑现诺言。 An explanation is here: https://stackoverflow.com/a/30790425/1432449 解释在这里: https : //stackoverflow.com/a/30790425/1432449
  • I do not believe it's different from putting next() inside of then() 我认为这与将next()放在then()内没有什么不同
  • I do not believe there is a best practices guide. 我认为没有最佳做法指南。 Cucumber is not a core focus of the Protractor team, and support for it is largely provided by the community on github. 黄瓜不是量角器团队的核心重点,它的支持大部分由GitHub上的社区提供。 If you or someone you know would like to write a best practices guide, we (the protractor team) would welcome a PR! 如果您或您认识的某个人想编写最佳实践指南,我们(量角器团队)将欢迎您参加PR!

What works for me is this - The function below searches for something that will always equal true - in the case the existence of a html tag. 对我有用的是-如果存在html标记,则下面的函数将搜索始终等于true的内容。 I call this function at the end of each test, passing in the callback 我在每次测试结束时都调用此函数,并传入回调

function callbackWhenDone(callback) {
    browser.wait(EC.presenceOf(element(by.css('html'))))
        .then(function () {callback();})
}

This is the usage in a simple test: 这是一个简单测试中的用法:

this.Given(/^I go on "([^"]*)"$/, function (arg1, callback) {
    browser.get('/' + arg1);
    callbackWhenDone(callback);
});

A bit of a hack I know but it gets the job done and looks pretty clean when used everywhere 我知道一点技巧,但是可以完成工作,并且在任何地方使用时看起来都非常干净

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM