mirror of
https://github.com/tbamud/tbamud.git
synced 2026-04-30 04:41:51 +02:00
CI: produce JUnit XML from Unity tests for GitHub test reporting
Agent-Logs-Url: https://github.com/tbamud/tbamud/sessions/0bc0c851-36e7-4d13-a393-517477e66c73 Co-authored-by: welcor <357770+welcor@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
d810782392
commit
73bda79fe6
73
tests/unity_to_junit.py
Normal file
73
tests/unity_to_junit.py
Normal file
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Convert Unity test-runner output to JUnit XML.
|
||||
|
||||
Usage:
|
||||
./test_binary | python3 unity_to_junit.py <suite_name> <output.xml>
|
||||
|
||||
Unity emits one result line per test:
|
||||
path/to/file.c:LINE:TEST_NAME:PASS
|
||||
path/to/file.c:LINE:TEST_NAME:FAIL:message
|
||||
path/to/file.c:LINE:TEST_NAME:IGNORE:message
|
||||
followed by a summary line:
|
||||
N Tests N Failures N Ignored
|
||||
"""
|
||||
|
||||
import re
|
||||
import sys
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
|
||||
def parse_unity(lines):
|
||||
tests = []
|
||||
total = failures = ignored = 0
|
||||
for line in lines:
|
||||
line = line.rstrip("\n")
|
||||
m = re.match(
|
||||
r"^.+:\d+:([^:]+):(PASS|FAIL|IGNORE)(?::(.*))?$", line
|
||||
)
|
||||
if m:
|
||||
name, result, message = m.group(1), m.group(2), m.group(3) or ""
|
||||
tests.append((name, result, message))
|
||||
continue
|
||||
m2 = re.match(r"^(\d+) Tests (\d+) Failures (\d+) Ignored", line)
|
||||
if m2:
|
||||
total, failures, ignored = int(m2.group(1)), int(m2.group(2)), int(m2.group(3))
|
||||
if not total:
|
||||
total = len(tests)
|
||||
failures = sum(1 for _, r, _ in tests if r == "FAIL")
|
||||
ignored = sum(1 for _, r, _ in tests if r == "IGNORE")
|
||||
return tests, total, failures, ignored
|
||||
|
||||
|
||||
def build_xml(suite_name, tests, total, failures, ignored):
|
||||
suite = ET.Element(
|
||||
"testsuite",
|
||||
name=suite_name,
|
||||
tests=str(total),
|
||||
failures=str(failures),
|
||||
errors="0",
|
||||
skipped=str(ignored),
|
||||
)
|
||||
for name, result, message in tests:
|
||||
case = ET.SubElement(suite, "testcase", name=name, classname=suite_name)
|
||||
if result == "FAIL":
|
||||
f = ET.SubElement(case, "failure", message=message)
|
||||
f.text = message
|
||||
elif result == "IGNORE":
|
||||
ET.SubElement(case, "skipped", message=message)
|
||||
return ET.ElementTree(suite)
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 3:
|
||||
print(f"usage: {sys.argv[0]} <suite_name> <output.xml>", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
suite_name, output_file = sys.argv[1], sys.argv[2]
|
||||
tests, total, failures, ignored = parse_unity(sys.stdin.readlines())
|
||||
tree = build_xml(suite_name, tests, total, failures, ignored)
|
||||
ET.indent(tree, space=" ")
|
||||
tree.write(output_file, encoding="unicode", xml_declaration=True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user