protractor-jasmine2-html-reporter在使用' shardTestFiles':在conf文件中为true时共享测试时,不会合并所有测试的结果

时间:2016-09-05 18:34:05

标签: jenkins jasmine protractor gulp-protractor jasmine-reporters

最近我们将我们的e2e测试配置为Jenkins& amp;很快我们意识到我们必须使用共享的测试文件:真正的选项,因为完整的套件运行需要很长时间才能让我们每天偷看9-10小时。但是当我们在conf文件中配置以下两个选项时。测试运行正常,但最终报告仅显示保存路径中的最后一个规格运行结果。合并所有选项并不能提供完整的报告。

请查看我们的配置文件详细信息。任何帮助将不胜感激。

根据Aditya提供的解决方案编辑conf文件。请帮忙

   var Jasmine2HtmlReporter = require('protractor-jasmine2-html-reporter');
var log4js = require('log4js');
var params = process.argv;
var args = process.argv.slice(3);

exports.config = {
  //seleniumServerJar: './node_modules/gulp-protractor/node_modules/protractor/selenium/selenium-server-standalone-2.48.2.jar',
  seleniumAddress: 'http://localhost:4444/wd/hub',
  allScriptsTimeout: 100000,
  framework: 'jasmine2',

  onPrepare: function () {

    return new Promise(function(fulfill, reject) {
      browser.getCapabilities().then(function(value) {
        reportName = value.get(Math.random(8,2)) + '_' + value.get('browserName') + '_' + Math.floor(Math.random() * 1E16);
        jasmine.getEnv().addReporter(
          new Jasmine2HtmlReporter({
            //cleanDestination: false,
            savePath: __dirname+'/target',
            //docTitle: 'Web UI Test Report',
            screenshotsFolder: 'image',
            //takeScreenshots: true,
            takeScreenshotsOnlyOnFailures: true,
            consolidate: true,
            consolidateAll: true,
             preserveDirectory: true,
            //fixedScreenshotName: true,
            filePrefix: reportName + ".html"
          })
        );
        fulfill();
      });
    });

    // browser.manage().timeouts().implicitlyWait(11000);
    var width = 768;
    var height = 1366;
    browser.driver.manage().window().setSize(768, 1366);
    browser.ignoreSynchronization = false; 
  },

  afterLaunch: function afterLaunch() {
    var fs = require('fs');
    var output = '';
    fs.readdirSync('target/').forEach(function (file) {
      if (!(fs.lstatSync('target/' + file).isDirectory()))
        output = output + fs.readFileSync('target/' + file);
    });
    fs.writeFileSync('target/ConsolidatedReport.html', output, 'utf8');

  },

  suites:{

    example:['./test/e2e/specs/**/*Spec.js',]
  },


  /*  capabilities: {
      'browserName': 'chrome'
    },*/

  multiCapabilities: [
    {
      'browserName': 'chrome'
    },
    {
      'browserName': 'firefox'
    }
  ],


  resultJsonOutputFile:'./results.json',

  // Options to be passed to Jasmine-node.
  jasmineNodeOpts: {
    showColors: true,
    defaultTimeoutInterval: 100000
  }
};

5 个答案:

答案 0 :(得分:2)

限制是使用'Jasmine2HtmlReporter',因为它会在测试并行运行时覆盖html报告文件。但是避免这种情况绝对是可能的,并且有几种方法可以做到这一点。根据您的方便选择正确的方式

1)修改Jasmine2HtmlReporter的'index.js'以附加文件而不是PhantomJs覆盖其使用

2)通过从onPrepare()函数配置Jasmine2HTML报告器生成唯一的HTML报告,并在以后合并所有报告

解决方案1:Jasmine2HtmlReporter的当前代码库 - index.js使用两个函数 - phantomWrite()& nodeWrite()写入数据。请参阅here

我创建了一个新函数 - appendwrite()来追加而不是覆盖并修改了代码以获取此函数 查看我从protractor-jasmine2-html-reporter

分叉的github代码

function appendwrite(path, filename, text){ var fs = require("fs"); var nodejs_path = require("path"); require("mkdirp").sync(path); // make sure the path exists var filepath = nodejs_path.join(path, filename); fs.appendFileSync(filepath,text) return; }

修改'node_modules / protractor-jasmine2-html-reporter / index.js'中的self.writeFile函数以获取新函数 try { appendwrite(path, filename, text); //phantomWrite(path, filename, text); return; } catch (e) { errors.push(' PhantomJs attempt: ' + e.message); } try { nodeWrite(path, filename, text); return; } catch (f) { errors.push(' NodeJS attempt: ' + f.message); }

并评论以下代码清除新运行的报告,以便您不会看到任何错误清除错误 - CleanUpCode

    rmdir(self.savePath);

解决方案2:通过在OnPrepare函数中配置Jasmine报告器,根据并行实例的sessionID生成单独的报告

onPrepare: function() { return new Promise(function (fulfill, reject) { browser.getCapabilities().then(function (value) { reportName = value.get('webdriver.remote.sessionid') + '_' + value.get('browserName') + '_' + Math.floor(Math.random()*1E16); jasmine.getEnv().addReporter( new Jasmine2HtmlReporter({ savePath: 'target/', screenshotsFolder: 'images', consolidate: true, consolidateAll: true, filePrefix: reportName + ".html" }) ); fulfill(); }) }); },

步骤2:完成完整测试并关闭所有webdriver会话后,整合afterLaunch()方法中跨并行实例生成的报告

afterLaunch: function afterLaunch() { var fs = require('fs'); var output = ''; fs.readdirSync('target/').forEach(function(file){ if(!(fs.lstatSync('target/' + file).isDirectory())) output = output + fs.readFileSync('target/' + file); }); fs.writeFileSync('target/ConsolidatedReport.html', output, 'utf8'); },

您还会看到使用一个ConsolidatedReport生成类似下面的报告 PS:请忽略任何拼写错误和语法错误。这只是作为一个例子,可以定制

enter image description here

EDIT1:我们用于命名HTML报告的'sessionID'是webdriver远程会话ID,如果您怀疑它可能不会通过多个会话保持唯一,只需为各个HTML报告生成一个随机数,然后合并

我修改了上面的代码

答案 1 :(得分:1)

我目前正在努力解决同样的问题,但是在我的原型设置中它正在工作,而我正在使用BASE配置,仅此而已。

var Jasmine2HtmlReporter = require('protractor-jasmine2-html-reporter');


exports.config = {
framework: 'jasmine',
seleniumAddress: 'http://localhost:4444/wd/hub',
specs: ['**-spec**.js'],

capabilities: {
    browserName: 'chrome',                                                      
    shardTestFiles: true,                                                        
    maxInstances: 2                                                             
},

onPrepare: function() {
    jasmine.getEnv().addReporter(
      new Jasmine2HtmlReporter({
        savePath: 'target/',
        screenshotsFolder: 'images',
        consolidate: true,
        consolidateAll: false  // false in my saved config - true in tut.
    })
  );
}
}

您能否看到您是否可以使用最低限度的分片报告?

编辑:还要关注目标文件夹中发生的事情,当你不想要它时,Jasmine可能会被覆盖/清理。

编辑2:如果你找到我下面的解决方案,请确保你推出足够的浏览器,因为你有规格 - 我下面的解决方案根据浏览器ID制作报告,如果你拆分你的规格:

capabilities: {
    browserName: 'chrome',                                                      
    shardTestFiles: true,                                                       
    maxInstances: **2**                                                             
},

如果你想要超过2,它会仍然覆盖你的记者HTML。它根据用于测试它的浏览器/会话ID创建一个HTML文件 - 如果你使用2个浏览器实例你会得到2个HTML文件,不多也不少。

编辑3:快速解决方法是不让茉莉花清理......

cleanDestination: false,

但这似乎没有做任何事情,所以在搜索和搜索之后 - 我不认为茉莉花html记者会让我们整合更多的规格,而不是我们有碎片。 github上的问题跟踪器没有显示任何进展。

所以我能想到的唯一解决方案是使用我下面的解决方案,使用足够的分片来支持你的规格,然后在完成后将其解析回一个文件。

编辑4:您始终可以滥用Jenkins在实际测试运行之间连接HTML文件。

答案 2 :(得分:0)

Aditya的解决方案对我来说很好。 我的示例配置文件: var Jasmine2HtmlReporter = require(' protractor-jasmine2-html-reporter');

exports.config = {     框架:' jasmine2',     seleniumAddress:' http://localhost:4444/wd/hub',     / multiCapabilities:[         {             ' browserName':' chrome',             ' shardTestFiles':是的,             ' maxInstances':2,             chromeOptions:{                 args:[' chrome.switches',' - 禁用扩展']             }         },         {             ' browserName':' firefox'         }     ], /     功能:     {         ' browserName':' chrome',         ' shardTestFiles':是的,         ' maxInstances':2,         chromeOptions:{             args:[' chrome.switches',' - 禁用扩展']         }     },     套房:{         登录页面:' login.js',         addproduct:' addproduct.js'     },     // specs:[' addproduct.js'],     jasmineNodeOpts:{         onComplete:null,         isVerbose:false,         includeStackTrace:是的,         showColors:是的,         defaultTimeoutInterval:30000     },

onPrepare: function() {
    return new Promise(function(fulfill, reject) {
        browser.getCapabilities().then(function(value) {
            reportName = value.get(Math.random(8,2)) + '_' + value.get('browserName') + '_' + Math.floor(Math.random() * 1E16);
            jasmine.getEnv().addReporter(
                new Jasmine2HtmlReporter({
                    //cleanDestination: false,
                    savePath: 'target/',
                    //docTitle: 'Web UI Test Report',
                    screenshotsFolder: 'image',
                    //takeScreenshots: true,
                    //takeScreenshotsOnlyOnFailures: true,
                    consolidate: true,
                    consolidateAll: true,
                   // preserveDirectory: true,
                    //fixedScreenshotName: true,
                    filePrefix: reportName + ".html"
                })
            );
            fulfill();
        });
    });
},
afterLaunch: function afterLaunch() {
    var fs = require('fs');
    var output = '';
    fs.readdirSync('target/').forEach(function(file) {
        if (!(fs.lstatSync('target/' + file).isDirectory()))
            output = output + fs.readFileSync('target/' + file);
    });
    fs.writeFileSync('target/ConsolidatedReport.html', output, 'utf8');
}

}

答案 3 :(得分:0)

我使用以下解决方案创建具有唯一时间戳的唯一文件夹。这将在date-timestamp文件夹中保存HTML报告,而不是Jasmin-2-html-reporter删除它。

var today = new Date();
   var timeStamp = today.getMonth() + 1 + '-' + today.getDate() + '-' + today.getFullYear() + '-' + 

today.getHours() + 'h-' + today.getMinutes() + 'm-' +today.getSeconds()+'s';

 jasmine.getEnv().addReporter(
            new Jasmine2HtmlReporter({
                savePath: './Reports/testResultsReport '+timeStamp,
                screenshotsFolder: 'screenPrints',
                takeScreenshots: true,
                takeScreenshotsOnlyOnFailures: true,
            })
        ); 

`

答案 4 :(得分:0)

这是另一种解决方案,它基于protractor-html-reporter-2构建在jasmine-reporters生成的xml文件上,并使用jasmine-reporters。但是// add relevant packages in package.json 'use strict'; const HTMLReport = require('protractor-html-reporter-2'); const jasmineReporters = require('jasmine-reporters'); const moment = require('moment'); const os = require('os'); const xmldoc = require('xmldoc'); ... const DATE_FORMAT = 'YYYYMMDD-HHmmss-SSS'; // use any other format that gives unique timestamp const reportDir = path.join(__dirname, '../report'); ... exports.config = { ... framework: 'jasmine', capabilities: { browserName: 'chrome', maxInstances: 2, shardTestFiles: true, }, beforeLaunch: async function () { // clean up report directory fs.emptyDirSync(reportDir); }, onPrepare: async function () { const NOW = moment().format(DATE_FORMAT); const reportName = 'index-' + NOW; jasmine.getEnv().addReporter(new jasmineReporters.JUnitXmlReporter({ consolidateAll: true, savePath: reportDir, filePrefix: reportName, })); }, onComplete: async function () { // do something after each instance of browser is closed }, afterLaunch: async function (exitCode) { // do something after ALL instances of browser are closed await consolidateJasmineXmlReports(); }, ... }, ... async function consolidateJasmineXmlReports() { // there may be better ways to write xml out but this works for me const files = fs.readdirSync(reportDir).filter(fn => fn.endsWith('.xml')); let disabledSum = 0; let errorsSum = 0; let failuresSum = 0; let testsSum = 0; let timeSum = 0; const allTestSuiteNodes = []; for (const file of files) { const pathToXml = reportDir + path.sep + file; console.log('Reading xml report file: ' + pathToXml); const xml = fs.readFileSync(pathToXml); const xmlDoc = new xmldoc.XmlDocument(xml); const disabled = parseInt(xmlDoc.attr.disabled); const errors = parseInt(xmlDoc.attr.errors); const failures = parseInt(xmlDoc.attr.failures); const tests = parseInt(xmlDoc.attr.tests); const time = parseFloat(xmlDoc.attr.time); disabledSum += disabled; errorsSum += errors; failuresSum += failures; testsSum += tests; timeSum += time; const testSuiteNodes = xmlDoc.childrenNamed('testsuite'); allTestSuiteNodes.push(testSuiteNodes); } let startXml = `<?xml version="1.0" encoding="UTF-8" ?>`; startXml += `<testsuites disabled="` + disabledSum + `" errors="` + errorsSum + `" failures="` + failuresSum + `" tests="` + testsSum + `" time="` + timeSum + `">`; const endXml = '</testsuites>'; allTestSuiteNodes.push(endXml); const finalXml = startXml + allTestSuiteNodes.join('\n'); fs.writeFileSync(reportDir + path.sep + 'consolidated.xml', finalXml, 'utf8'); const testConfig = { outputPath: reportDir, outputFilename: 'consolidated', ... }; new HTMLReport().from(reportDir + path.sep + 'consolidated.xml', testConfig); } 没有任何选择来处理由多个浏览器实例生成的报告。在找不到理想的解决方案后,我最终在量角器config js文件中执行了以下操作:

afterLaunch

逻辑是

  1. 确保所有xml文件的唯一名称。
  2. 将所有xml文件组合为afterLaunch中的一个有效xml。
  3. 使用任何使用该xml文件的软件包在Open Blue Ocean Jenkins中生成html。

我们使用Jenkins进行测试,并且以上创建的报告在Jenkins中显示良好,并且还可以在 SELECT (select max(ID) from ORDERS) as ID, (select max(DATE) from ORDERS) as DATE, SUM(TOTAL_VALUE), SUM(QUANTITY) FROM ( SELECT distinct O.ID , O.DATE , max (O.TOTAL_VALUE) TOTAL_VALUE , SUM (OI.QUANTITY ) over(partition by O.ID) QUANTITY FROM ORDERS O INNER JOIN ORDERS_ITEMS OI ON O.ID = OI.ID WHERE O.DATE >= (GetDate() - 90) -- SELECT last 90 days group by O.ID,OI.QUANTITY,O.DATE )A 插件显示的报告中准确显示。

注意:我已经使用shardTestFiles进行了测试,而不是使用multiCapabilities进行了测试,但是我认为它也应该可以使用。

另请参阅: