junit.py 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  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. import os
  8. import re
  9. import xml.etree.ElementTree as ET
  10. import resulttool.resultutils as resultutils
  11. def junit(args, logger):
  12. testresults = resultutils.load_resultsdata(args.json_file, configmap=resultutils.store_map)
  13. total_time = 0
  14. skipped = 0
  15. failures = 0
  16. errors = 0
  17. for tests in testresults.values():
  18. results = tests[next(reversed(tests))].get("result", {})
  19. for result_id, result in results.items():
  20. # filter out ptestresult.rawlogs and ptestresult.sections
  21. if re.search(r'\.test_', result_id):
  22. total_time += result.get("duration", 0)
  23. if result['status'] == "FAILED":
  24. failures += 1
  25. elif result['status'] == "ERROR":
  26. errors += 1
  27. elif result['status'] == "SKIPPED":
  28. skipped += 1
  29. testsuites_node = ET.Element("testsuites")
  30. testsuites_node.set("time", "%s" % total_time)
  31. testsuite_node = ET.SubElement(testsuites_node, "testsuite")
  32. testsuite_node.set("name", "Testimage")
  33. testsuite_node.set("time", "%s" % total_time)
  34. testsuite_node.set("tests", "%s" % len(results))
  35. testsuite_node.set("failures", "%s" % failures)
  36. testsuite_node.set("errors", "%s" % errors)
  37. testsuite_node.set("skipped", "%s" % skipped)
  38. for result_id, result in results.items():
  39. if re.search(r'\.test_', result_id):
  40. testcase_node = ET.SubElement(testsuite_node, "testcase", {
  41. "name": result_id,
  42. "classname": "Testimage",
  43. "time": str(result['duration'])
  44. })
  45. if result['status'] == "SKIPPED":
  46. ET.SubElement(testcase_node, "skipped", message=result['log'])
  47. elif result['status'] == "FAILED":
  48. ET.SubElement(testcase_node, "failure", message=result['log'])
  49. elif result['status'] == "ERROR":
  50. ET.SubElement(testcase_node, "error", message=result['log'])
  51. tree = ET.ElementTree(testsuites_node)
  52. if args.junit_xml_path is None:
  53. args.junit_xml_path = os.environ['BUILDDIR'] + '/tmp/log/oeqa/junit.xml'
  54. tree.write(args.junit_xml_path, encoding='UTF-8', xml_declaration=True)
  55. logger.info('Saved JUnit XML report as %s' % args.junit_xml_path)
  56. def register_commands(subparsers):
  57. """Register subcommands from this plugin"""
  58. parser_build = subparsers.add_parser('junit', help='create test report in JUnit XML format',
  59. description='generate unit test report in JUnit XML format based on the latest test results in the testresults.json.',
  60. group='analysis')
  61. parser_build.set_defaults(func=junit)
  62. parser_build.add_argument('json_file',
  63. help='json file should point to the testresults.json')
  64. parser_build.add_argument('-j', '--junit_xml_path',
  65. help='junit xml path allows setting the path of the generated test report. The default location is <build_dir>/tmp/log/oeqa/junit.xml')