Что сделано () и как его использовать (транспортир, жасмин)
it('should for something', function check(done) {
browser.sleep(2000);
$('.csTx').isPresent().then(function(result) {
if(result) {
done();
} else {
xPage.clickBack();
check(done);
}
})
}, 30000);
Может кто-нибудь объяснить, как done() работает и для чего это нужно. Я прогуглил это, но не могу найти информацию, которая была бы достаточно легкой для меня, чтобы понять. Я автоматизируюсь с транспортиром и жасмином. пожалуйста, рассмотрите приведенный выше код.
2 ответа
Вам нужно использовать done
если ваш тест создает параллельный TaskQueue в потоке управления вашего теста (подробнее об обещаниях и потоке управления).
Например:
describe('Control Flow', function() {
function logFromPromise(text) {
var deferred = protractor.promise.defer();
deferred.then(function() {
console.log(text);
});
deferred.fulfill();
return deferred;
}
it('multiple control flows', function() {
setTimeout(function() {
logFromPromise('1');
});
logFromPromise('0');
});
}
призвание setTime
создает параллельную очередь задач в элементе управления:
ControlFlow
| TaskQueue
| | Task<Run fit("multiple control flows") in control flow>
| | | TaskQueue
| | | | Task <logFromPromise('0');>
| TaskQueue
| | Task <setTimeout>
Транспортир считает, что тест "сделан" после 0
печатается. В этом примере 1
вероятно будет напечатан после завершения теста. Заставить транспортира ждать Task <setTimeout>
Вам нужно вызвать готовую функцию:
it('multiple control flows', function(done) {
setTimeout(function() {
logFromPromise('1').then(function() {
done();
});
});
logFromPromise('0');
});
Если вы можете, пусть транспортир справится, когда тест "завершен". Наличие параллельных TaskQueues может привести к неожиданным условиям гонки в вашем тесте.
Вот образец describe
что вы можете бежать и посмотреть, что происходит. Я должен упомянуть, что я не использую Protractor, поэтому могут существовать некоторые дополнительные соображения относительно его конкретных возможностей.
describe('Done functionality', function(){
var echoInOneSecond = function(value){
console.log('creating promise for ', value);
return new Promise(function(resolve, reject){
console.log('resolving with ', value);
resolve(value);
});
};
it('#1 this will untruly PASS', function(){
var p = echoInOneSecond('value #1');
p.then(function(value){
console.log('#1 expecting...and value is ', value);
expect(value).toBe('value #1');
});
});
it('#2 this will NOT FAIL', function(){
var p = echoInOneSecond('value #2');
p.then(function(value){
console.log('#2 expecting... and value is ', value);
expect(value).not.toBe('value #2');
});
});
it('3 = will truly FAIl', function(done){
var p = echoInOneSecond('value #3');
p.then(function(value){
console.log('#3 expecting... and value is ', value);
expect(value).not.toBe('value #3');
done();
});
});
it('4 = this will truly PASS', function(done){
var p = echoInOneSecond('value #4');
p.then(function(value){
console.log('#4 expecting... and value is ', value);
expect(value).toBe('value #4');
done();
});
});
});
при запуске теста вы заметите последовательность: первые обещания #1, #2, #3 будут созданы и разрешены одно за другим. Обратите внимание, что ожидание для № 1 и № 2 еще не будет выполнено, потому что обещания разрешаются асинхронно.
Затем, так как тест № 3 использует done
, после создания обещания № 3, функции для then
Все предыдущие обещания оцениваются: вы увидите "# 1 ожидают..." и "# 2 ожидают...", но Жасмин не будет беспокоиться об этом, потому что тесты № 1 и № 2 уже завершены, и все, что касается они сделали. Только после того, как это ожидание № 3 будет сделано, и оно действительно потерпит неудачу, потому что жасмин заботится обо всем, что происходит раньше done()
сделан.
И затем вы можете посмотреть # 4 теста нормального потока - создание обещания, решения, ожидания, всего, что рассматривает Жасмин, так что ожидание действительно пройдет.
Я не использовал транспортир. Для Жасмин я понимаю, что done
марки Jasmine
подождите, но не в традиционном смысле времени ожидания. Это не похоже на таймер, который всегда работает. Я думаю done
действует как контрольно-пропускной пункт в Jasmine
, когда Jasmine
видит, что спецификация использует done
, он знает, что не может перейти к следующему шагу (скажем, запустить следующую спецификацию или пометить эту спецификацию как завершенную, т.е. объявить вердикт текущей спецификации), если часть кода, содержащая done
был запущен.
Например, jasmine передает эту спецификацию, даже если она потерпит неудачу, поскольку не ожидает вызова setTimeout.
fit('lets check done',()=>{
let i=0;
setTimeout(function(){
console.log("in timeout");
expect(i).toBeTruthy();//the spec should fail as i is 0 but Jasmine passes it!
},1000);
//jasmine reaches this point and see there is no expectation so it passes the spec. It doesn't wait for the async setTimeout code to run
});
Но если мое намерение состоит в том, чтобы Жасмин ждала асинхронный код в setTimeout
тогда я использую done
в асинхронном коде
fit('lets check done',(done)=>{
let i=0;
setTimeout(function(){
console.log("in timeout");
expect(i).toBeTruthy();//with done, the spec now correctly fails with reason Expected 0 to be truthy.
done();//this should make jasmine wait for this code leg to be called before declaring the verdict of this spec
},1000);
});
Обратите внимание, что done
должен называться там, где я хочу проверить утверждения.
fit('lets check done',(done)=>{
let i=0;
setTimeout(function(){
console.log("in timeout");
expect(i).toBeTruthy();//done not used at the right place, so spec will incorrectly ypass again!.
//done should have been called here as I am asserting in this code leg.
},1000);
done();//using done here is not right as this code leg will be hit inn normal execution of it.
});
Подводя итог, представьте, что все сделано как "Жасмин" - "Я закончил сейчас" или "Я закончу, когда этот код появится"