如何将Karate测试报告生成与执行分离并合并多Runner报告?
Karate报告合并与执行逻辑分离方案咨询
我们近期对测试Runner进行了更新,可将多个测试执行合并为单个测试任务,当前已实现合并生成单份Cucumber报告,但Karate报告仍与单个Runner绑定。希望了解:是否可将Karate报告的生成逻辑与测试执行分离(类似Cucumber报告的实现方式),或提供方法将子目录中的所有Karate汇总报告合并到父目录中?
现有实现代码
总Runner代码(EquipmentRunner_AllInOne)
package net.equipment.runners; import java.io.File; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; import net.masterthought.cucumber.Configuration; import net.masterthought.cucumber.ReportBuilder; import org.apache.commons.io.FileUtils; import org.junit.jupiter.api.Test; public class EquipmentRunner_AllInOne { private static final String serviceName = "EquipmentService"; private static final String reportRoot = "target/" + serviceName + "/"; private static final String dtStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); @Test public void testParallel() { _EquipmentRunnerDomainV1 v1 = new _EquipmentRunnerDomainV1() .reportDir(reportRoot + dtStamp + "/domain/v1") .buildDir(reportRoot + dtStamp); v1.concatRunner(); _EquipmentRunnerDomainV2 v2 = new _EquipmentRunnerDomainV2() .reportDir(reportRoot + dtStamp + "/domain/v2") .buildDir(reportRoot + dtStamp); v2.concatRunner(); // _EquipmentRunnerDomainV3 v3 = new _EquipmentRunnerDomainV3() // .reportDir(reportRoot + dtStamp + "/domain/v3") // .buildDir(reportRoot + dtStamp); // v3.concatRunner(); // _EquipmentRunnerDomainV4 v4 = new _EquipmentRunnerDomainV4() // .reportDir(reportRoot + dtStamp + "/domain/v4") // .buildDir(reportRoot + dtStamp); // v4.concatRunner(); // _EquipmentRunnerGraph graph = new _EquipmentRunnerGraph() // .reportDir(reportRoot + dtStamp + "/graph") // .buildDir(reportRoot + dtStamp); // Graph.concatRunner(); Collection<File> jsonFiles = FileUtils.listFiles(new File(reportRoot + dtStamp), new String[] { "json" }, true); List<String> jsonPaths = new ArrayList<>(jsonFiles.size()); jsonFiles.forEach(file -> jsonPaths.add(file.getAbsolutePath())); Configuration config = new Configuration(new File("target"), serviceName); ReportBuilder reportBuilder = new ReportBuilder(jsonPaths, config); reportBuilder.generateReports(); } }
单个子Runner代码(_EquipmentRunnerDomainV1)
package net.equipment.runners; import com.intuit.karate.Results; import com.intuit.karate.Runner; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.List; import net.masterthought.cucumber.Configuration; import net.masterthought.cucumber.ReportBuilder; import org.apache.commons.io.FileUtils; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; public class _EquipmentRunnerDomainV1 { private static final String serviceName = "EquipmentService"; private static final String reportRoot = "target/" + serviceName + "/"; private static final Integer cores = Runtime.getRuntime().availableProcessors(); public String _path = "classpath:net/equipment/test/api/domain/v1"; public String[] _tags = { "@regression", "@hopper" }; public String _karateEnv = "dev"; public String _buildDir = reportRoot + "/"; public String _reportDir = reportRoot + "/domain/v1"; public _EquipmentRunnerDomainV1() { } public _EquipmentRunnerDomainV1 path(String _path) { this._path = _path; return this; } public _EquipmentRunnerDomainV1 tags(String[] _tags) { this._tags = _tags; return this; } public _EquipmentRunnerDomainV1 karateEnv(String _karateEnv) { this._karateEnv = _karateEnv; return this; } public _EquipmentRunnerDomainV1 buildDir(String _buildDir) { this._buildDir = _buildDir; return this; } public _EquipmentRunnerDomainV1 reportDir(String _reportDir) { this._reportDir = _reportDir; return this; } // Allows concatenated execution of runner @Test public void concatRunner() { Results results = Runner .path(_path) .tags(_tags) .karateEnv(_karateEnv) .outputCucumberJson(true) .outputHtmlReport(true) .outputJunitXml(true) .buildDir(_buildDir) .reportDir(_reportDir) .systemProperty("karate.dsRow", "1") .parallel(cores); assertEquals(0, results.getFailCount(), results.getErrorMessages()); } // Allows manual execution of runner with results @Test public void testParallel() { Results results = Runner .path("classpath:net/equipment/test/api/domain/v1") .tags("@regression", "@hopper") .karateEnv(_karateEnv) .outputCucumberJson(true) .outputHtmlReport(true) .outputJunitXml(true) .reportDir(_reportDir) .systemProperty("karate.dsRow", "1") .parallel(cores); generateReport(results.getReportDir()); assertEquals(0, results.getFailCount(), results.getErrorMessages()); } public static void generateReport(String karateOutputPath) { Collection<File> jsonFiles = FileUtils.listFiles(new File(karateOutputPath), new String[] { "json" }, true); List<String> jsonPaths = new ArrayList<>(jsonFiles.size()); jsonFiles.forEach(file -> jsonPaths.add(file.getAbsolutePath())); Configuration config = new Configuration(new File("target"), serviceName); ReportBuilder reportBuilder = new ReportBuilder(jsonPaths, config); reportBuilder.generateReports(); } }
解决方案
1. 分离Karate报告生成逻辑(推荐)
和Cucumber报告的实现逻辑对齐,让测试执行只生成JSON结果,统一在总Runner中生成合并报告:
- 修改子Runner:将
outputHtmlReport(true)改为outputHtmlReport(false),关闭单个Runner的自动HTML报告生成,保留outputCucumberJson(true)用于生成JSON结果 - 扩展总Runner:在总Runner的
testParallel方法末尾添加代码,收集所有子Runner的Karate JSON结果,调用Karate的ReportGenerator生成合并后的HTML报告:
// 合并生成Karate总报告 File karateReportDir = new File(reportRoot + dtStamp + "/karate-merged-report"); List<String> karateJsonPaths = new ArrayList<>(); // 收集所有子目录下的Karate JSON文件(默认前缀为karate-) FileUtils.listFiles(new File(reportRoot + dtStamp), new String[]{"json"}, true).forEach(file -> { if (file.getName().startsWith("karate-")) { karateJsonPaths.add(file.getAbsolutePath()); } }); // 初始化Karate报告生成器并生成合并报告 com.intuit.karate.report.ReportGenerator generator = new com.intuit.karate.report.ReportGenerator(karateJsonPaths, karateReportDir, serviceName); generator.generateHtml();
2. 合并已生成的子目录Karate报告
如果已经生成了子目录的Karate报告,最可靠的方式是基于JSON源重新生成合并报告(即上述方案)。若需直接合并HTML内容,可通过以下方式:
- 遍历所有子目录的Karate报告HTML,提取测试结果片段
- 自定义HTML模板,将所有片段整合到一份总报告中
不过这种方式维护成本高,不如基于JSON重新生成灵活可靠。
注意事项
- 确保子Runner的
outputCucumberJson(true)保持开启,这是生成合并报告的数据基础 - 调整文件收集逻辑时,注意区分Karate JSON和Cucumber JSON(Karate默认生成的JSON文件名以
karate-开头) - 若使用Karate版本较旧,需确认
ReportGenerator类的包路径和方法是否兼容
内容的提问来源于stack exchange,提问作者mike
相关产品推荐
相关产品推荐

