梦魇:错误:超过2000毫秒的超时。对于异步测试和钩子

时间:2017-03-08 06:23:13

标签: javascript nightmare

我开始尝试使用Nightmare和mocha进行自动化测试。我收到了下面的错误,尽管遵循了错误本身的指令。

var Nightmare = require('nightmare');
var expect = require('chai').expect;

var url = 'http://www.google.com/'

describe('Page availability', function() {
  it('Should open homepage', function(done) {
    var nightmare = Nightmare();

    nightmare
      .goto(url)
      .wait('body')
      .evaluate(function () {
        return document.querySelector('.gb_P').innerHTML
      })
      .end()
      .then(function(text) {
        expect(text).to.equal('images');
        done();
      })
  });
});

用`mocha test.js'运行上面的脚本时,这是我得到的输出:

Page availability
    1) Should open homepage


  0 passing (2s)
  1 failing

  1) Page availability Should open homepage:
     Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.

忏悔:我还没有(还)熟悉承诺,但我不明白为什么摩卡没有考虑到我所做的完成回调在里面提供。

2 个答案:

答案 0 :(得分:1)

这是因为Mocha的默认超时时间为2秒,您的梦魇动作可能需要比完成时间更长的时间。 (Google花了很长时间才完成加载。)

describeit内,您可以设置this.timeout(ms),或在运行mocha命令时使用--timeout [ms]

答案 1 :(得分:0)

我一直在努力解决这个完全相同的问题几个小时,终于找到了一个有效的解决方案!

首先@Ross在这里是正确的,虽然2秒可以足够,但总是没有足够的时间等待谷歌,或任何其他页面。出于这个原因,我将我的超时时间提高到了15000毫秒,这是一个安全的赌注,也许是过度杀戮,但除非你的网络连接非常慢,否则你将是安全的。

其次,我发现了

querySelector(selector).innerHTML

经常返回null。这可能是因为编写选择器路径时涉及大量人为错误,或者使用javascript或噩梦.evaluate()函数在幕后发生了一些其他技术问题。

值得一提的是,问题似乎并非来自wait()函数,因为我发现框架使用相同的查询选择器非常高兴,但交换了innerHTML属性length属性。

示例:

除了.evaluate()返回null:

之外,这将导致超时错误
.wait("body > div.wrap > h1")
   .evaluate(() => {
        return document.querySelectorAll("body > div.wrap > h1").innerHTML;
    })

而将innerHTML更改为length将完全正常

.wait("body > div.wrap > h1")
   .evaluate(() => {
        return document.querySelectorAll("body > div.wrap > h1").length;
    })
但是,我不确定为什么这是我的发现。

因此,为了解决OP的问题,我使用了document.getElementsByClassName(),这已经向我证明了获取DOM元素的更简单和/或更准确的方法

重写OP的代码:

var Nightmare = require('nightmare');
var expect = require('chai').expect;

var url = 'http://www.google.com/'

describe('Page availability', function() {
    this.timeout(15000);
    it('Should open homepage', function(done) {
        var nightmare = Nightmare();

        nightmare
        .goto(url)
        .wait('body')
        .evaluate(function () {
            var headerDiv = document.getElementsByClassName("gb_P");
            return headerDiv[1].innerHTML
        })
        .end()
        .then(function(text) {
            expect(text).to.equal('Images');
            done();
        })
    });
});

产生通过测试。

此外,OP已经忘记利用图像'这是该类的innerHTML。

总结

我不是querySelector(selector).innerHTML仍可以使用,但是,针对特定的类和ID getElementById()是更安全的选择。它们也可以串联工作,例如下面的代码运行时没有错误,因为在querySelector(selector).innerHTML中干扰整个查询选择器会导致测试崩溃。

.wait("body > div#wpwrap > div#wpcontent > div#wpbody > div#wpbody-content > div.wrap > h1")
    .evaluate(() => {
        var headerDiv = document.getElementById("wpbody-content");
        h1Html = headerDiv.querySelector(".wrap h1").innerHTML;
        return h1Html;
    })