【问题标题】:what done() is for and how to use it ( protractor, jasmine)done() 的用途和使用方法(量角器、茉莉花)
【发布时间】:2019-02-01 14:42:00
【问题描述】:
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() 是如何工作的以及它是做什么用的。我用谷歌搜索了它,但找不到任何容易让我理解的信息。我正在使用量角器和茉莉花进行自动化。请考虑上面的代码。

【问题讨论】:

  • 这只是一个回调,表示此规范已完成。在调用 done() 之前,您将一直使用此规范
  • @Gunderson - 你能告诉我更多关于它的信息吗?

标签: jasmine protractor


【解决方案1】:

如果您的测试在测试的控制流中创建了一个并行任务队列,您需要使用done(阅读更多关于promises and control flow 的信息)。

例如:

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 后,Protractor 认为测试已“完成”。在本例中,1 可能会在测试完成后打印。要让量角器等待Task &lt;setTimeout&gt;,需要调用done函数:

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

如果可以,请在“完成”测试时让量角器处理。拥有并行任务队列可能会导致测试中出现意外的竞争条件。

【讨论】:

    【解决方案2】:

    这是一个示例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 的期望将不会运行,因为 Promise 是异步解决的。

    然后,由于 #3 测试使用 done,在创建 #3 Promise 之后,将评估所有先前 Promise 的 thens 的函数:您将看到 '#1 Expecting...' 和 '#2 Expecting ...',但 jasmine 不会在意这些,因为测试 #1 和 #2 已经完成,并且所有与它们有关的事情都已完成。只有在做出了第 3 个期望之后,它才会真正失败,因为 jasmine 确实会处理在产生 done() 之前发生的所有事情。

    然后您可以观看 #4 测试正常流程——创建承诺、解决、期望,茉莉花考虑的一切,因此期望将真正通过。

    【讨论】:

    • 我认为量角器处理 done() 本身。这就是为什么使用它来运行规范的原因。但寻找一些关于这方面的信息,基本上是量角器如何处理以及我应该什么时候不应该使用它。感谢您的广泛回复
    【解决方案3】:

    我没用过量角器。对于 Jasmine,我的理解是 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
      });
    

    但如果我的意图是让 Jasmine 等待 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.
      });
    

    总而言之,将 done 视为告诉 Jasmine - “我现在完成了”或“当此代码命中时我将完成”

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多