what done() is for and how to use it ( protractor, jasmine)

三世轮回 提交于 2020-01-01 05:28:31

问题


it('should for something', function check(done) {
  browser.sleep(2000);
  $('.csTx').isPresent().then(function(result) {
    if(result) {
      done();
    } else {
      xPage.clickBack();
      check(done);
    }
  })
}, 30000);

Can someone explain how done() works and what this is for. I googled it but cannot find any information that would be easy enough for me to understand. I am automating with protractor and jasmine. please consider the above code.


回答1:


You need to use done if your test creates a parallel TaskQueue in your test's Control Flow (read more about promises and control flow).

For example:

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

Calling setTime creates a parallel Task Queue in the control:

ControlFlow
| TaskQueue
| | Task<Run fit("multiple control flows") in control flow>
| | | TaskQueue 
| | | | Task <logFromPromise('0');>
| TaskQueue
| | Task <setTimeout>

Protractor thinks the test is "done" after 0 is printed. In this example, 1 will probably be printed after the test is completed. To make protractor wait for Task <setTimeout>, you need to call the done function:

    it('multiple control flows', function(done) {
        setTimeout(function() {
            logFromPromise('1').then(function() {
                done();
            });
        });
        logFromPromise('0');
    });

If you can, let protractor handle when the test is "done". Having parallel TaskQueues can lead to unexpected race conditions in your test.




回答2:


Here is a sample describe that you can run and see what happens. I have to mention that I don't use Protractor so there might exist some additional considerations to be made concerning its specific capabilities.

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

when running the test you will note the sequence: first promises #1, #2, #3 will be created and resolved one by one. Please note that expectation for #1 and #2 will not be run yet because promises are resolved asynchronously.

Then, since #3 test uses done, after #3 promise is created, functions for thens of all previous promises are evaluated: you will see '#1 expecting...' and '#2 expecting...', but jasmine won't care about that because tests #1 and #2 are already finished and everything concerning them done. Only after those #3 expectation is made and it will truly fail because jasmine does take care of everything that happens before done() is made.

And then you can watch #4 test normal flow -- creating promise, resolving, expectation, everything considered by jasmine so expectation will truly pass.




回答3:


I haven't used Protractor. For Jasmine, my understanding is that done makes Jasmine wait but not in the traditional sense of timeout. It is not like a timer which is always run. I think done acts as a checkpoint in Jasmine. When Jasmine sees that a spec uses done, it knows that it cannot proceed to the next step (say run next spec or mark this spec as finished i.e. declare verdict of the current spec) unless the code leg containing done has been run.

For example, jasmine passes this spec even though it should fail as it doesn't wait for setTimeout to be called.

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

But if my intention is that Jasmine waits for the the async code in setTimeout, then I use done in the async code

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

Note that done should be called where I want to check the assertions.

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

In summary, think of done as telling Jasmine - "I am done now" or "I'll be done when this code hits"



来源:https://stackoverflow.com/questions/42281591/what-done-is-for-and-how-to-use-it-protractor-jasmine

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!