Jasmine 如何在并行执行量角器测试脚本时生成合并报告?

Jasmine 如何在并行执行量角器测试脚本时生成合并报告?,jasmine,protractor,Jasmine,Protractor,我的量角器套件有15个规格。我希望并行运行这些脚本,并希望在此执行过程中生成合并报告 通过在配置文件中添加标记“shardTestFiles:true”,我可以并行运行脚本。但是,我无法获得合并报告(仅在报告中获取最后执行的规范的结果) 我正在寻找在并行执行量角器脚本的同时生成合并报告的解决方案 注意:使用jasmine reporter生成报告。您可以使用reporter并提供一个用于合并测试结果的选项。例如: var Jasmine2HtmlReporter = require('prot

我的量角器套件有15个规格。我希望并行运行这些脚本,并希望在此执行过程中生成合并报告

通过在配置文件中添加标记“shardTestFiles:true”,我可以并行运行脚本。但是,我无法获得合并报告(仅在报告中获取最后执行的规范的结果)

我正在寻找在并行执行量角器脚本的同时生成合并报告的解决方案

注意:使用jasmine reporter生成报告。

您可以使用reporter并提供一个用于合并测试结果的选项。例如:

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

    jasmine.getEnv().addReporter(
        new Jasmine2HtmlReporter({
            savePath: 'testReports/',
            screenshotsFolder: 'images',
            takeScreenshotsOnlyOnFailures: true,
            consolidateAll: true,
            consolidate: true,
            cleanDestination: false
        }));
您可以使用reporter并提供用于合并测试结果的选项。例如:

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

    jasmine.getEnv().addReporter(
        new Jasmine2HtmlReporter({
            savePath: 'testReports/',
            screenshotsFolder: 'images',
            takeScreenshotsOnlyOnFailures: true,
            consolidateAll: true,
            consolidate: true,
            cleanDestination: false
        }));

我遵循下面提到的方法来满足我的需求

  • 我在配置文件的onPrepare部分保存了以下代码。这将为每个规范生成一个报告

    onPrepare() {
    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); // eslint-disable-line
              jasmine.getEnv().addReporter(
                new Jasmine2HtmlReporter({
                  savePath: 'e2e/Results',
                  screenshotsFolder: 'images',
                  takeScreenshotsOnlyOnFailures: true,
                  consolidate: true,
                  consolidateAll: true,
                  cleanDestination: false,
                  fileName: "my-report.html",
                  fileName: "regression-test-report.html",
                  fileNamePrefix: reportName,
                })
              );
              fulfill();
            })
          });
        });
    },
    
    并将以下代码保存在afterLaunch部分,该部分将合并onPrepare部分生成的所有报告:

    afterLaunch: function afterLaunch() {
        var fs = require('fs');
        var output = '';
        fs.readdirSync('e2e/Results/').forEach(function(file){
          if(!(fs.lstatSync('e2e/Results/' + file).isDirectory()))
            output = output + fs.readFileSync('e2e/Results/' + file);
        });
        fs.writeFileSync('e2e/Results/RegressionTestReport.html', output, 'utf8');
      }
    
  • 上述配置后面临的挑战:我能够通过在配置文件中写入上述配置,通过并行执行来合并报表。但是,如果我再次运行脚本,报表也会合并该脚本(我不想这样做)。使标记“cleanDestination:true”在每个规范的执行结束后删除。因此,它不起作用


    我是如何解决这个问题的?:我使用shell脚本在jenkins中运行脚本。因此,我编写了shell命令“rm-fr e2e/Results”,在执行脚本之前删除报表文件夹。因此,每次都会删除报表,并在最新执行时生成一个新的合并报表。

    我接着e以下提到的方法,以满足我的需要

  • 我在配置文件的onPrepare部分保存了以下代码。这将为每个规范生成一个报告

    onPrepare() {
    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); // eslint-disable-line
              jasmine.getEnv().addReporter(
                new Jasmine2HtmlReporter({
                  savePath: 'e2e/Results',
                  screenshotsFolder: 'images',
                  takeScreenshotsOnlyOnFailures: true,
                  consolidate: true,
                  consolidateAll: true,
                  cleanDestination: false,
                  fileName: "my-report.html",
                  fileName: "regression-test-report.html",
                  fileNamePrefix: reportName,
                })
              );
              fulfill();
            })
          });
        });
    },
    
    并将以下代码保存在afterLaunch部分,该部分将合并onPrepare部分生成的所有报告:

    afterLaunch: function afterLaunch() {
        var fs = require('fs');
        var output = '';
        fs.readdirSync('e2e/Results/').forEach(function(file){
          if(!(fs.lstatSync('e2e/Results/' + file).isDirectory()))
            output = output + fs.readFileSync('e2e/Results/' + file);
        });
        fs.writeFileSync('e2e/Results/RegressionTestReport.html', output, 'utf8');
      }
    
  • 上述配置后面临的挑战:我能够通过在配置文件中写入上述配置,通过并行执行来合并报表。但是,如果我再次运行脚本,报表也会合并该脚本(我不想这样做)。使标记“cleanDestination:true”在每个规范的执行结束后删除。因此,它不起作用


    我是如何解决这个问题的?:我使用shell脚本在jenkins中运行脚本。因此,我编写了shell命令“rm-fr e2e/Results”,在执行脚本之前删除报表文件夹。因此,每次都会删除报表,并在最新执行时生成新的合并报表。

    我尝试了
    dragrator-jasmine2-html-reporter
    与链接答案中的建议相结合,但不喜欢输出。我喜欢由
    dragrator-html-reporter-2
    生成的输出,该输出适用于由
    jasmine reporters
    生成的xml文件。但它没有任何选项可用于由多实例生成的报告在找不到理想的解决方案后,我在量角器配置js文件中执行了以下操作:

    // 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);
    }
    
    //在package.json中添加相关包
    "严格使用",;
    常量HTMLReport=require('dragrator-html-reporter-2');
    const jasmineReporters=require('jasmine-reporters');
    恒力矩=要求的(‘力矩’);
    const os=要求('os');
    const xmldoc=require('xmldoc');
    ...
    const DATE_FORMAT='yyyyymmdd HHmmss SSS';//使用提供唯一时间戳的任何其他格式
    const reportDir=path.join(_dirname,../report');
    ...
    exports.config={
    ...
    框架:“茉莉花”,
    能力:{
    browserName:“chrome”,
    最大实例:2,
    shardTestFiles:对,
    },
    启动前:异步函数(){
    //清理报告目录
    fs.emptyDirSync(reportDir);
    }, 
    onPrepare:async函数(){
    const NOW=moment().format(日期格式);
    const reportName='index-'+NOW;
    jasmine.getEnv().addReporter(新的jasmineReporters.JUnitXmlReporter({
    是的,
    保存路径:reportDir,
    filePrefix:reportName,
    }));
    },
    onComplete:异步函数(){
    //关闭浏览器的每个实例后执行某些操作
    },
    启动后:异步功能(exitCode){
    //关闭浏览器的所有实例后执行某些操作
    等待consolidateJasmineXmlReports();
    },
    ...     
    },
    ...
    异步函数consolidateJasmineXmlReports(){
    //也许有更好的方法写出xml,但这对我来说很有用
    const files=fs.readdirSync(reportDir.filter)(fn=>fn.endsWith('.xml'));
    设disabledSum=0;
    设errorsSum=0;
    设故障sum=0;
    设testsSum=0;
    设timeSum=0;
    常量allTestSuiteNodes=[];
    for(文件的常量文件){
    const pathToXml=reportDir+path.sep+文件;
    log('读取xml报告文件:'+pathToXml);
    constxml=fs.readFileSync(pathToXml);
    const xmlDoc=新的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+=已禁用;
    errorsSum+=错误;
    故障SUM+=故障;
    testsSum+=测试;
    timeSum+=时间;
    const testSuiteNodes=xmlDoc.childrenNamed('testsuite');
    所有testSuiteNodes.push(testSuiteNodes);
    }
    让startXml=`;
    startXml+=`;
    constendxml='';
    allTestSuiteNodes.push(endXml);
    const finalXml=startXml+allTestSuiteN