Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a to_junit method to standardize the report format of TestSuiteResult #1703

37 changes: 36 additions & 1 deletion giskard/core/suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
from dataclasses import dataclass
from functools import singledispatchmethod

from xml.etree.ElementTree import Element, SubElement, tostring
from xml.dom import minidom
from mlflow import MlflowClient

from giskard.client.dtos import SuiteInfo, SuiteTestDTO, TestInputDTO, TestSuiteDTO
from giskard.client.giskard_client import GiskardClient
from giskard.core.core import TestFunctionMeta
Expand Down Expand Up @@ -156,6 +157,40 @@ def to_wandb(self, run: Optional["wandb.wandb_sdk.wandb_run.Run"] = None) -> Non
run.log({"Test suite results/Test-Suite Results": wandb.Table(columns=columns, data=data)})


def to_junit(self):
"""Convert the test suite result to JUnit XML format."""
testsuites = Element('testsuites', {'tests': str(len(self.results))})

for test_tuple in self.results:
test_name, test, _ = test_tuple
testsuite = SubElement(testsuites, 'testsuite', {
'name': f"Test {test_name} (metric={test.metric})",
})
testcase = SubElement(testsuite, 'testcase', {'name': test.metric_name, 'time': str(test.metric)}) # replace with actual time

if not test.passed:
failure = SubElement(testcase, 'failure', {
'message': f"Test failed with metric of {test.metric}",
'type': "TestFailed" if not test.is_error else "Error"
})
# Add full test result information here
for k, v in test.__dict__.items():
if k != 'messages' and k != 'is_error':
SubElement(failure, 'detail', {'name': k, 'value': str(v)})
for message in test.messages:
SubElement(failure, 'detail', {'name': 'message', 'value': message})
else:
# Add test result information here
for k, v in test.__dict__.items():
if k != 'messages' and k != 'is_error':
SubElement(testcase, 'detail', {'name': k, 'value': str(v)})
for message in test.messages:
SubElement(testcase, 'detail', {'name': 'message', 'value': message})

# Convert to string
xml_str = minidom.parseString(tostring(testsuites)).toprettyxml(indent=" ")
return xml_str

class SuiteInput:
"""Represents an input parameter for a test suite.

Expand Down
Loading