当internjs中的测试失败时,如何截取屏幕截图?

时间:2015-01-08 22:35:49

标签: screenshot intern

我在解决如何在InternJs中测试失败时如何截取屏幕截图时遇到问题。我在registerSuite中进行了这个简单的测试;

'verify google homepage': function () {
    var url = 'https://www.google.com/';
    return this.remote
        .get(url)
        .getCurrentUrl()
        .then(function (data) {
            assert.strictEqual(data, url, 'Incorrect URL');
        })
        .findByName('q')
            .click()
 }

我可以使用以下代码创建截图;

.takeScreenshot
.then(function (data) {
    fs.writeFileSync('/path/to/some/file', data, 'base64');
)}

如果上述测试未通过断言或无法找到定位器,我只想截取屏幕截图。

我查看了afterEach方法,但我无法弄清楚如何获取上一次测试的状态以应用条件。

所以我的问题是,有没有人设置他们的internjs测试只能截取失败的屏幕截图以及它是如何完成的?

5 个答案:

答案 0 :(得分:3)

  1. 目前无法通过beforeEachafterEach方法与当前正在执行的测试进行交互;这种能力将在下一版的实习生中出现。

  2. 默认情况下,Selenium服务器提供每个Selenium命令失败的屏幕截图,这是error.detail.screen属性上的Buffer对象。如果Selenium命令失败,只需使用已有屏幕截图等待您的属性。

  3. 对于断言失败,您可以创建一个简单的承诺助手来为您截取屏幕截图:

  4. function screenshotOnError(callback) {
      return function () {
        try {
          return callback.apply(this, arguments);
        }
        catch (error) {
          return this.remote.takeScreenshot().then(function (buffer) {
            fs.writeFileSync('/path/to/some/file', buffer);
            throw error;
          });
        }
      };
    }
    
    // ...
    
    'verify google homepage': function () {
      return this.remote.get(url).getCurrentUrl().then(screenshotOnError(function (actualUrl) {
        assert.strictEqual(actualUrl, url);
      }));
    }
    

    如果像这样手动包装所有回调太不方便,您还可以创建并使用自定义界面来注册您的测试,以类似的方式自动包装测试功能。我将把它作为读者的练习。

答案 1 :(得分:0)

您可以在链的末尾使用catch方法,并按照C Snover的建议使用error.detail.screen。

'verify google homepage': function () {
    return this.remote
        .get(require.toUrl('./fixture.html'))
        .findById('operation')
            .click()
            .type('hello, world')
        .end()
        .findById('submit')
            .click()
        .end()
        .catch(function(error){
          fs.writeFileSync('/tmp/screenshot.png', error.detail.screen);
        })
}

答案 2 :(得分:0)

我今天一直在玩这个,并且已经设法将它用于整个套件,而不是需要将代码添加到每个似乎相当不必要的测试中。

var counter = -1,
suite = {
    beforeEach: function () {
        counter++;
    },
    afterEach: function () {
        var currentTest = this.tests[counter];
        if (!currentTest.error) {
            return;
        }
        this.remote
            .takeScreenshot().then(function (buffer) {
                if (!fs.existsSync(path)) {
                    fs.mkdirSync(path);
                }
                fs.writeFileSync('/tmp/' + currentTest.name + '.png', buffer);
            });
    }
};

您需要做的烦人的事情是为每个测试套件而不是“全局”执行此操作,但比为每次测试执行此操作要好得多。

答案 3 :(得分:0)

根据this issue,从Intern 3.0开始,您可以执行自定义报告,在测试失败时获取屏幕截图。因此,您可以通过简单的方式集中管理它,只需在config.js中引用自定义报告者即可。在我的情况下,我可以在config.js中添加一个报告器数组,其中包含我的自定义数组的路径:

reporters: [
        { id: 'tests/support/ScreenShot' }
],

比我制作一个自定义的报道者覆盖testFail

'use strict';

define([
    'intern/dojo/node!fs',
], function(fs) {

    function ScreenShot(config) {
        config = config || {};
    }

    ScreenShot.prototype.testFail = function(test) {
        test.remote.takeScreenshot().then(function(buffer) {

            try {
                fs.writeFileSync('./screenshots/' + test.parent.name.replace(/ /g, '') + '-' +
                    test.name.replace(/ /g, '') + '.png', buffer);

            } catch (err) {
                console.log('Failed to take a screenshot: ' + err);
            }
        });
    };

    return ScreenShot;
});

注意引用自定义报告者和屏幕截图位置的相对路径。他们似乎都在考虑您运行intern-runner的位置,而不是源文件所在的位置。 有关自定义记者的更多信息,请转到this page

答案 4 :(得分:0)

以Hugo Oshiro的答案为基础,

// tests/support/CleanScreenshots.js

define([
  'intern/dojo/node!path',
  'intern/dojo/node!del',
], function(path, del) {

  return new Promise((resolve, reject) => {
    let directory = 'tests/screenshots';
    del(path.join(directory, '**/*'))
      .then(resolve)
      .catch(reject);
  });

});

然后在你的实习生配置中:

/* global define */

define([
    'tests/support/CleanScreenshots'
  ], function (CleanScreenshots) {


  return {

    ...

    setup: function () {
      return CleanScreenshots();
    },

    ...

  };
});