【问题标题】:How do I take a screenshot when a test in internjs fails?当 internjs 中的测试失败时如何截取屏幕截图?
【发布时间】:2015-01-08 22:35:49
【问题描述】:

我在弄清楚如何仅在 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 方法,但不知道如何获取最后一个测试的状态以应用条件。

所以我的问题是,有没有人将他们的实习生测试设置为只对失败进行截图以及它是如何完成的?

【问题讨论】:

    标签: screenshot intern


    【解决方案1】:
    1. 目前无法通过beforeEachafterEach 方法与当前正在执行的测试进行交互;此功能将在下一版本的 Intern 中提供。

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

    3. 对于断言失败,您可以创建一个简单的 Promise 助手为您截屏:

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

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

    【讨论】:

    • 谢谢。这正是我想要的。
    【解决方案2】:

    您可以在链的末尾使用 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);
            })
    }
    

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

        【解决方案4】:

        基于 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();
            },
        
            ...
        
          };
        });
        

        【讨论】:

          【解决方案5】:

          根据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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2018-09-04
            • 2020-10-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-09-07
            • 1970-01-01
            相关资源
            最近更新 更多