Files
mongo/buildscripts/create_bazel_test_report.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

81 lines
2.2 KiB
Python
Raw Normal View History

import json
import time
from glob import glob
from typing import List
import typer
from typing_extensions import TypedDict
from util.expansions import get_expansion
from buildscripts.parse_test_xml import parse_test_xml
class Result(TypedDict):
"""A single test result"""
status: str
test_file: str
log_raw: str
start: float
end: float
class Report(TypedDict):
"""Test report for Evergreen"""
results: List[Result]
def main(testlog_dir: str):
"""Create an report.json for Evergreen from bazel test logs."""
if not get_expansion("create_bazel_test_report"):
print(
"Expansion create_bazel_test_report is not set, skipping creating a report from Bazel test logs."
)
return
report = Report({"results": []})
for test_xml in glob(f"{testlog_dir}/**/test.xml", recursive=True):
testsuite = parse_test_xml(test_xml).find("testsuite")
testcase = testsuite.find("testcase")
# Replace part of the name added by the remote test wrapper script
test_file = testcase.attrib["name"].replace("_ci_wrapper", "")
if testcase.find("error") is not None:
status = "fail"
else:
status = "pass"
log_raw = testsuite.find("system-out").text
# Bazel gives just a duration, while Evergreen expects a start and end
# time to calculate the duration. Evergreen itself does something similar
# for when only a duration is known.
duration = testcase.attrib["time"]
start = time.time()
end = start + int(duration)
report["results"].append(
Result(
{
"test_file": test_file,
"status": status,
"start": start,
"end": end,
"log_raw": log_raw,
}
)
)
if report["results"]:
with open("report.json", "wt") as fh:
json.dump(report, fh)
else:
print(f"No test.xml found within {testlog_dir}. Not creating a report.")
if __name__ == "__main__":
typer.run(main)