我正在使用Mocha/Chai制作一个Protractor测试套件(是的,我在Jasmine中遇到了同样的问题)。
因为应用程序是相当复杂的,我希望能够干燥地设置测试套件,允许我将操作链接到函数中。(例如,"登录,然后浏览到[parameterX],然后浏览到[parameter],然后期望第一个帖子标题是[parameterZ])。
但是当我把它们放在.then()语句中时,我似乎很难让Mocha运行测试。
下面是一小段代码片段,它显示了我所指的行为。
var chai = require('chai');
var cAP = require('chai-as-promised')
chai.use(cAP);
const expect = chai.expect;
const doTest = (x) => {
describe('main', function() {
it('should return foo', function(done) {
expect(x).to.equal('foo')
})
})
}
const wait = () => new Promise((resolve, reject) => {
setTimeout(() => resolve(), 10000)
})
wait()
.then(() => doTest('foo'))
/* results in
* 0 passing (4ms)
*/
describe
和it
块不能异步完成。如果你想在测试执行前等待10秒,你应该使用before
块,它支持异步执行。你的before
回调有一个参数,它是done
回调。在这个block中,你可以等待10秒,然后调用done。所有后续的块都将等待,直到done
从before
块中被调用。
describe('your tests', () => {
before(done => {
setTimeout(done, 10000)
})
it('should return foo', () => {
expect(x).to.equal('foo')
})
})
问题是您正在异步创建您的测试套件。默认情况下,Mocha不允许异步创建套件。我拿了你的代码,并做了以下更改:
-
从传递给
it
的回调中删除done
参数,因为它是无用的。 -
我在
doTest
结束时增加了对run
的呼叫 -
我用
--delay
选项调用Mocha:mocha --delay
.
--delay
选项将使Mocha等待构建测试套件。您可以通过调用run()
来表示您已经完成了构建。以下是包含上述更改的完整代码:
var chai = require('chai');
var cAP = require('chai-as-promised')
chai.use(cAP);
const expect = chai.expect;
const doTest = (x) => {
describe('main', function() {
it('should return foo', function() {
expect(x).to.equal('foo')
})
})
run();
}
const wait = () => new Promise((resolve, reject) => {
setTimeout(() => resolve(), 10000)
})
wait()
.then(() => doTest('foo'))
chai-as-promise可以让它更简洁一些
/**
* Modified by cool.blue on 26-Aug-16.
*/
'use strict';
var chai = require('chai');
var cAP = require('chai-as-promised');
chai.use(cAP);
const should = chai.should();
const wait5 = (something) => new Promise((resolve, reject) => {
setTimeout(() => resolve(something + 5), 5000)
});
const wait10 = (something) => new Promise((resolve, reject) => {
setTimeout(() => resolve(something + 10), 10000)
});
const doTest = (x, y, prep) => {
describe('main', function() {
this.timeout(15000);
it('should return the right number for ' + x + ' and ' + y, function() {
return prep(y).should.become(x)
})
})
};
[[17, 12, wait5], [15, 5, wait10], [15, 5, wait5]].forEach((listing) => doTest(...listing));
但是,要小心箭头函数:它们对语句和表达式的处理是不同的。
it('should return the right number for ' + x + ' and ' + y,
() => prep(y).should.become(x)
)
与
完全不同it('should return the right number for ' + x + ' and ' + y, () => {
prep(y).should.become(x)
})
但与
完全相同it('should return the right number for ' + x + ' and ' + y, () => {
return prep(y).should.become(x)
})
箭头函数让我紧张,这就是为什么我更喜欢…
it('should return the right number for ' + x + ' and ' + y, function() {
return prep(y).should.become(x)
})
我找不到确切的答案,但我找到了一些东西,可以满足我真正需要的东西,所以,这就是我所做的。
基本上,我可以将所有其他异步操作作为参数传递给测试函数,并且可以使用before块的done()回调来确保它们在正确的时间执行。
const wait5 = (something) => new Promise((resolve, reject) => {
setTimeout(() => resolve(something + 5), 5000)
})
const wait10 = (something) => new Promise((resolve, reject) => {
setTimeout(() => resolve(something + 10), 10000)
})
const doTest = (x, y, prep) => {
describe('main', function() {
let z;
before(function (done) {
this.timeout(30000);
prep(y).then((val) => {
z = val;
done();
})
})
it('should return the right number for ' + x + ' and ' + y, () => {
expect(x).to.equal(z)
})
})
}
[[17, 12, wait5], [15, 5, wait10], [15, 5, wait5]].forEach((listing) => doTest(...listing))
/* Result:
main
√ should return the right number for 17 and 12
main
√ should return the right number for 15 and 5
main
1) should return the right number for 15 and 5
2 passing (20s)
1 failing
1) main should return the right number for 15 and 5:
AssertionError: expected 15 to equal 10
+ expected - actual
-15
+10
*/