Selenium (Node.js) screenshots are too slow

时间:2018-03-08 22:14:28

标签: javascript node.js selenium mocha screenshot

I am using Selenium + Mocha (in Node.js) to do some UI testing on a site. After each test, I want to capture a screen shot so that I can review/share the visible results.

However, after the basic UI changes are made (i.e. insert text and hit submit), there is an AJAX call + JavaScript animation that triggers after that I would like to be part of my screen shot.

The screenshots I'm getting appear to be in taken after the next step has already started. (So, the first test runs > trigger the screenshot > second test starts > screenshot is actually captured)

I've tried .sleep() and timeouts -- however my use could have been wrong.

function takeScreenshot(name='out'){
      driver.takeScreenshot().then(function(data){
        var base64Data = data.replace(/^data:image\/png;base64,/,"")
        fs.writeFile(`screenshots/${name}.png`, base64Data, 'base64', function(err) {
          if(err) console.log(err);
        });
      });
}

describe('UI Tests', async function() {

  before(async function() {
    driver = await new Builder().forBrowser('chrome').build();
    await driver.get('http://localhost:8000').then( async function(){ await getAssets(); });
    /* search | submit | reset are declared in getAssets() */
  });

  after(async function() {
    driver.quit();
  });

  afterEach(async function(){
    step++;
    driver.sleep(3000).then(
      takeScreenshot(step) 
    );
  });

  describe('User Types/Modifies Input and Submits Query', async function() {

    it('type in search + click submit', async function(){
        search.sendKeys("Puppies and Kittens");
        submit.click();
    });

    it('click the X icon to clear search', async function(){
        reset.click();
    });

  });

});

In the above snippet, the screenshot for the first test ('type in search + click submit') would show the input field already cleared from the second test.

1 个答案:

答案 0 :(得分:1)

发送到selenium的命令是异步的,这意味着函数将安排工作在将来的某个时刻运行,但会立即返回,以便代码继续运行。

在selenium-webdrivers案例中,函数返回" promise"这将在未来的某个时候解决。摩卡可以使用承诺等待结果。

承诺和摩卡

Mocha使用测试的返回值来确定它是否应该等待解析的承诺。您可以使用await.then控制承诺流程。

如果正在使用Promise A+代码,那么测试中您将始终拥有return someFormOfPromise

it(waits, function(){
  return Promise.resolve(true)
    .then(res => expect(res).to.be.true)
})

如果正在使用async,则可以保证返回承诺但您必须await任何异步或测试将继续

it(waits, async function(){
  let res = await Promise.resolve(true)
  expect(res).to.be.true
})

回调类似,但它们使用done函数来指示测试继续进行。

it(waits, function(done){
  someTrueCallback((err, res) => {
    if (err) return done(err)
    expect(res).to.be.true
    done()
  }) 
})

在发布的代码中有很多混合Promise A+async,甚至还有一个回调。选择一种方式并尽可能坚持下去,我&# 39; ll使用async / await

回复承诺

任何异步回调都可以转换为promises,因此从fs.writeFile回调函数开始,将其转换为promise:

function writeFile(path, data, format){
  return new Promise((resolve, reject)=>{
    fs.writeFile(path, data, format, function(err){
      if (err) return reject(err)
      resolve(true)
    })
  })
}

幸运的是,这是非常标准的,Node.js在util.promisify中有一个帮助,所以帮助者可以成为:

const writeFile = util.promisify(fs.writeFile)

function async takeScreenshot(name='out'){
    let data = await driver.takeScreenshot()
    var base64Data = data.replace(/^data:image\/png;base64,/,"")
    return await writeFile(`screenshots/${name}.png`, base64Data, 'base64')
}

测试

await可用时,无需使用.then

每当调用返回promise的函数时,如果要使用已解析的值,则可能需要awaitlet res = await...

describe('UI Tests', function() {

  before(async function() {
    driver = await new Builder().forBrowser('chrome').build();
    await driver.get('http://localhost:8000')
    await getAssets()
    /* search | submit | reset are declared in getAssets() */
  });

  after(async function() {
    await driver.quit();
  });

  afterEach(async function(){
    step++;
    await takeScreenshot(step) 
  });

  describe('User Types/Modifies Input and Submits Query', function() {

    it('type in search + click submit', async function(){
        await search.sendKeys("Puppies and Kittens");
        await submit.click();
    });

    it('click the X icon to clear search', async function(){
        await reset.click();
    });

  });

});

作为旁注,这些测试实际上并没有检查任何东西。通常情况下,会使用像chai这样的断言库来确保事物符合expect的方式。