summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClara Kowalsky <clara.kowalsky@siemens.com>2024-08-28 11:20:27 +0200
committerRichard Purdie <richard.purdie@linuxfoundation.org>2024-08-29 21:58:19 +0100
commit5aeabd3217da2a7ce9f789d5d224f6682b4555a1 (patch)
treec81f98c3e1a608ae71917e2f87fd640f70254a67
parentf4f9ebf6fb7da7605298c95187a70c118e0ab02e (diff)
downloadpoky-5aeabd3217da2a7ce9f789d5d224f6682b4555a1.tar.gz
resulttool: Add support to create test report in JUnit XML format
This adds the functionality to convert the results of the testresults.json file to a unit test report in JUnit XML format. The unit test report can be used in the CI/CD pipeline to display the test results. To use the resulttool scripts, first source oe environment, then run the entry point script to look for help. $ resulttool To generate the unit test report, execute the below $ resulttool junit <json_file> By default the unit test report is stored as <build_dir>/tmp/log/oeqa/junit.xml. (From OE-Core rev: 3f9be03946243feaa09b908d7010899769091fe6) Signed-off-by: Clara Kowalsky <clara.kowalsky@siemens.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--scripts/lib/resulttool/junit.py77
-rwxr-xr-xscripts/resulttool5
2 files changed, 82 insertions, 0 deletions
diff --git a/scripts/lib/resulttool/junit.py b/scripts/lib/resulttool/junit.py
new file mode 100644
index 0000000000..c7a53dc550
--- /dev/null
+++ b/scripts/lib/resulttool/junit.py
@@ -0,0 +1,77 @@
1# resulttool - report test results in JUnit XML format
2#
3# Copyright (c) 2024, Siemens AG.
4#
5# SPDX-License-Identifier: GPL-2.0-only
6#
7
8import os
9import re
10import xml.etree.ElementTree as ET
11import resulttool.resultutils as resultutils
12
13def junit(args, logger):
14 testresults = resultutils.load_resultsdata(args.json_file, configmap=resultutils.store_map)
15
16 total_time = 0
17 skipped = 0
18 failures = 0
19 errors = 0
20
21 for tests in testresults.values():
22 results = tests[next(reversed(tests))].get("result", {})
23
24 for result_id, result in results.items():
25 # filter out ptestresult.rawlogs and ptestresult.sections
26 if re.search(r'\.test_', result_id):
27 total_time += result.get("duration", 0)
28
29 if result['status'] == "FAILED":
30 failures += 1
31 elif result['status'] == "ERROR":
32 errors += 1
33 elif result['status'] == "SKIPPED":
34 skipped += 1
35
36 testsuites_node = ET.Element("testsuites")
37 testsuites_node.set("time", "%s" % total_time)
38 testsuite_node = ET.SubElement(testsuites_node, "testsuite")
39 testsuite_node.set("name", "Testimage")
40 testsuite_node.set("time", "%s" % total_time)
41 testsuite_node.set("tests", "%s" % len(results))
42 testsuite_node.set("failures", "%s" % failures)
43 testsuite_node.set("errors", "%s" % errors)
44 testsuite_node.set("skipped", "%s" % skipped)
45
46 for result_id, result in results.items():
47 if re.search(r'\.test_', result_id):
48 testcase_node = ET.SubElement(testsuite_node, "testcase", {
49 "name": result_id,
50 "classname": "Testimage",
51 "time": str(result['duration'])
52 })
53 if result['status'] == "SKIPPED":
54 ET.SubElement(testcase_node, "skipped", message=result['log'])
55 elif result['status'] == "FAILED":
56 ET.SubElement(testcase_node, "failure", message=result['log'])
57 elif result['status'] == "ERROR":
58 ET.SubElement(testcase_node, "error", message=result['log'])
59
60 tree = ET.ElementTree(testsuites_node)
61
62 if args.junit_xml_path is None:
63 args.junit_xml_path = os.environ['BUILDDIR'] + '/tmp/log/oeqa/junit.xml'
64 tree.write(args.junit_xml_path, encoding='UTF-8', xml_declaration=True)
65
66 logger.info('Saved JUnit XML report as %s' % args.junit_xml_path)
67
68def register_commands(subparsers):
69 """Register subcommands from this plugin"""
70 parser_build = subparsers.add_parser('junit', help='create test report in JUnit XML format',
71 description='generate unit test report in JUnit XML format based on the latest test results in the testresults.json.',
72 group='analysis')
73 parser_build.set_defaults(func=junit)
74 parser_build.add_argument('json_file',
75 help='json file should point to the testresults.json')
76 parser_build.add_argument('-j', '--junit_xml_path',
77 help='junit xml path allows setting the path of the generated test report. The default location is <build_dir>/tmp/log/oeqa/junit.xml')
diff --git a/scripts/resulttool b/scripts/resulttool
index fc282bda6c..66a6af9959 100755
--- a/scripts/resulttool
+++ b/scripts/resulttool
@@ -15,6 +15,9 @@
15# To report test report, execute the below 15# To report test report, execute the below
16# $ resulttool report <source_dir> 16# $ resulttool report <source_dir>
17# 17#
18# To create a unit test report in JUnit XML format, execute the below
19# $ resulttool junit <json_file>
20#
18# To perform regression file analysis, execute the below 21# To perform regression file analysis, execute the below
19# $ resulttool regression-file <base_result_file> <target_result_file> 22# $ resulttool regression-file <base_result_file> <target_result_file>
20# 23#
@@ -43,6 +46,7 @@ import resulttool.regression
43import resulttool.report 46import resulttool.report
44import resulttool.manualexecution 47import resulttool.manualexecution
45import resulttool.log 48import resulttool.log
49import resulttool.junit
46logger = scriptutils.logger_create('resulttool') 50logger = scriptutils.logger_create('resulttool')
47 51
48def main(): 52def main():
@@ -61,6 +65,7 @@ def main():
61 resulttool.regression.register_commands(subparsers) 65 resulttool.regression.register_commands(subparsers)
62 resulttool.report.register_commands(subparsers) 66 resulttool.report.register_commands(subparsers)
63 resulttool.log.register_commands(subparsers) 67 resulttool.log.register_commands(subparsers)
68 resulttool.junit.register_commands(subparsers)
64 69
65 args = parser.parse_args() 70 args = parser.parse_args()
66 if args.debug: 71 if args.debug: