使用Chai as promises解决了Protractor和Cucumber中的承诺问题
Resolving promises in Protractor and Cucumber using Chai as Promised
最近,我和一位同事在使用Protractor和Chai as promise实现黄瓜步骤定义的"正确"方式上发生了一些分歧。我们的争论来自于双方都缺乏对Cucumber上下文中的promise resolution到底是怎么回事的理解。
我们是针对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);
});
然而,我的同事争辩说,为了满足承诺决议,你需要把你的期望和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;
});
});
});
});
我觉得后者真的错了,但我也不知道前者是否正确。我对最终()的理解是,它的工作方式类似于then(),因为它在继续之前等待承诺解决。我希望前一个示例按顺序等待每个expect()调用,然后在最后的expect()中通过notify()调用next(),向cucumber发出信号,使其继续进行下一步。
更令人困惑的是,我观察到其他同事这样写他们的期望:
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()那样强制执行同步行为? and.notify(next)的真正作用是什么?它与在then()中调用next()不同吗?
- 有没有我们还没有找到的最佳实践指南,可以更清楚地说明这一点?
提前感谢。
- 你的感觉是正确的,你的同事错了(尽管这是一个合理的错误!)Protractor在运行第二个WebDriver命令之前会自动等待一个WebDriver命令解析。因此,在第二个代码块中,
-
eventually
解析承诺。解释在这里:https://stackoverflow.com/a/30790425/1432449 - 我不认为这和把
next()
放在then()
里面有什么不同 - 我不相信有一个最佳实践指南。Cucumber并不是Protractor团队的核心关注点,对它的支持主要由github上的社区提供。如果您或您认识的人愿意编写最佳实践指南,我们(量角器团队)将欢迎PR!
element(by.button('Run Search')).isPresent()
将不会解析,直到element(by.model('optionsBox')).isPresent()
和element(by.model('searchTerms')).isPresent()
完成。对我来说是这样的-下面的函数搜索总是等于true的东西-在html标记存在的情况下。我在每次测试结束时调用这个函数,并传入回调
function callbackWhenDone(callback) {
browser.wait(EC.presenceOf(element(by.css('html'))))
.then(function () {callback();})
}
在一个简单的测试中的用法:
this.Given(/^I go on "([^"]*)"$/, function (arg1, callback) {
browser.get('/' + arg1);
callbackWhenDone(callback);
});
我知道这是一个hack,但是它完成了工作,看起来很干净,当在任何地方使用
- 我的职位回报太快了,如何做出承诺
- 打破承诺链的好方法是什么
- 从函数返回角度承诺
- 我怎样才能获得承诺的价值
- 延期承诺值未更新/解析/延期
- 在承诺链中处理早期回报的最佳方式
- 承诺在非节点式回调上使用Bluebird
- 简单的ES6承诺问题-交换解决和拒绝参数
- 组合承诺和非承诺值
- 带有对象/原型的链式承诺(Q延期)
- AngularJS$q承诺使用socket.io
- React JS:未捕获(在承诺中)语法错误:在位置 0 的 JSON 中意外<令牌
- 当一些承诺失败时,如何继续使用$q.all()
- Nodejs和express路由,如何处理客户端的承诺
- 如何在多承诺链中处理谷歌地图API V3事件
- 承诺合并流
- JavaScript承诺-无法读取属性'那么'的未定义
- 等待循环调用的所有承诺完成
- Pg承诺性能提升:在冲突中
- 使用Chai as promises解决了Protractor和Cucumber中的承诺问题