Jasmine 如何在所有测试完成后(而不是每个文件)生成分片量角器测试报告?
当切分测试(也称为并行运行测试;即:Jasmine 如何在所有测试完成后(而不是每个文件)生成分片量角器测试报告?,jasmine,protractor,Jasmine,Protractor,当切分测试(也称为并行运行测试;即:shardTestFiles:true)时,量角器不会在所有测试完成时报告结果,而是在完成时报告每个文件的结果 有人对此有解决办法吗? 我尝试过使用内联钩子teardown和postest,但都没有改变这种行为(仍然是每个测试文件报告)。我也尝试过在onPrepare之外设置记者,但也没有乐趣 我希望有一个简单的解决办法。。。但我发现人们把他们的结果放在数据库里也就不足为奇了。。。这也是一个可以接受的答案 恐怕没有一个简单的答案,因为在使用任何自定义插件时,量
shardTestFiles:true
)时,量角器不会在所有测试完成时报告结果,而是在完成时报告每个文件的结果
有人对此有解决办法吗?
我尝试过使用内联钩子teardown
和postest
,但都没有改变这种行为(仍然是每个测试文件报告)。我也尝试过在onPrepare
之外设置记者,但也没有乐趣
我希望有一个简单的解决办法。。。但我发现人们把他们的结果放在数据库里也就不足为奇了。。。这也是一个可以接受的答案 恐怕没有一个简单的答案,因为在使用任何自定义插件时,量角器都会覆盖报告文件。但下面这两个对我有用。 选择最适合你的 1) 修补Jasmine2HtmlReporter的'index.js'以附加文件,而不是使用PhantomJs覆盖文件 2) 通过从onPrepare()函数配置Jasmine2HTML reporter生成唯一的HTML报告,并在以后合并所有报告 解决方案1:Jasmine2HtmlReporter-
index.js
的当前代码库使用两个函数--phantomWrite()
&nodeWrite()
来写入数据。提及
我创建了一个新函数-appendwrite()
以进行追加而不是覆盖,并修改了代码以提取此函数
查看我的github代码,它是从
函数appendwrite(路径、文件名、文本){
var fs=要求(“fs”);
var nodejs_path=require(“路径”);
require(“mkdirp”).sync(path);//确保路径存在
var filepath=nodejs_path.join(路径,文件名);
fs.appendFileSync(文件路径,文本)
返回;
}
并修改“node_modules/dragrator-jasmine2-html-reporter/index.js”中的self.writeFile
函数以获取新函数
试一试{
追加写入(路径、文件名、文本);
//phantomWrite(路径、文件名、文本);
返回;
}catch(e){errors.push('PhantomJs trunt:'+e.message);}
试一试{
nodeWrite(路径、文件名、文本);
返回;
}catch(f){errors.push('NodeJS trunt:'+f.message);}
并注释以下在新运行时清理报告的代码,以便您不会看到任何错误清理错误-
解决方案2:通过在OnPrepare函数中配置Jasmine reporter,基于sessionID为并行实例生成单独的报告
onPrepare:function(){
返回新承诺(功能(履行、拒绝){
browser.getCapabilities().then(函数(值){
reportName=value.get('webdriver.remote.sessionid')+'+'value.get('browserName')+''+'Math.floor(Math.random()*1E16);
jasmine.getEnv().addReporter(
新Jasmine2HtmlReporter({
保存路径:“目标/”,
截屏文件夹:“图像”,
对,,
是的,
filePrefix:reportName+“.html”
})
);
实现();
})
});
},
步骤2:完成测试并关闭所有webdriver会话后,在afterLaunch()方法中合并跨并行实例生成的报告
afterLaunch:函数afterLaunch(){
var fs=需要('fs');
var输出=“”;
fs.readdirSync('target/').forEach(函数(文件){
if(!(fs.lstatSync('target/'+file.isDirectory()))
output=output+fs.readFileSync('target/'+file);
});
writeFileSync('target/ConsolidatedReport.html',output'utf8');
},
您将看到下面生成的报告,其中还包含一个合并的报告
请忽略任何打字错误和语法错误。这只是一个示例,可以定制
我在前面的解决方案2>步骤1中找到了答案。根据最新版本的html reporter,filePrefix应为fileNamePrefix,因此函数应为:
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,
fileNamePrefix: reportName + ".html"
})
);
fulfill();
})
});
},
下面是另一个解决方案,在这个基础上,使用
gravor-html-reporter-2
,它可以处理由jasmine reporters
生成的xml文件。但是,jasmine reporters
没有任何选项来处理由多个浏览器实例生成的报告。在未能找到理想的解决方案后,我最终在量角器配置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_格式='YYYYMMDD 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:异步函数(){
//关闭浏览器的每个实例后执行某些操作
},
启动后:异步功能(exitCo
// 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);
}