tracie: Produce JUnit XML results
Write tracie results to the 'results/junit.xml' file using the JUnit XML format. Among other uses, this file can be picked up by gitlab to display more useful information to the user. Signed-off-by: Alexandros Frantzis <alexandros.frantzis@collabora.com> Reviewed-by: Eric Anholt <eric@anholt.net> Reviewed-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6598>
This commit is contained in:
@@ -2,6 +2,7 @@ import logging
|
|||||||
import pytest
|
import pytest
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
|
||||||
from os import environ, chdir
|
from os import environ, chdir
|
||||||
from os.path import dirname, exists, realpath
|
from os.path import dirname, exists, realpath
|
||||||
@@ -10,6 +11,7 @@ import tracie
|
|||||||
|
|
||||||
|
|
||||||
RESULTS_YAML = "results/results.yml"
|
RESULTS_YAML = "results/results.yml"
|
||||||
|
JUNIT_XML = "results/junit.xml"
|
||||||
TRACE_LOG_TEST1 = "results/trace1/test/gl-test-device/magenta.testtrace.log"
|
TRACE_LOG_TEST1 = "results/trace1/test/gl-test-device/magenta.testtrace.log"
|
||||||
TRACE_LOG_TEST2 = "results/trace2/test/vk-test-device/olive.testtrace.log"
|
TRACE_LOG_TEST2 = "results/trace2/test/vk-test-device/olive.testtrace.log"
|
||||||
TRACE_PNG_TEST1 = "results/trace1/test/gl-test-device/magenta.testtrace-0.png"
|
TRACE_PNG_TEST1 = "results/trace1/test/gl-test-device/magenta.testtrace-0.png"
|
||||||
@@ -215,3 +217,37 @@ def test_tracie_stores_images_on_request():
|
|||||||
assert run_tracie()
|
assert run_tracie()
|
||||||
assert exists(TRACE_PNG_TEST1)
|
assert exists(TRACE_PNG_TEST1)
|
||||||
assert exists(TRACE_PNG_TEST2)
|
assert exists(TRACE_PNG_TEST2)
|
||||||
|
|
||||||
|
def test_tracie_writes_junit_xml():
|
||||||
|
assert run_tracie()
|
||||||
|
junit_xml = ET.parse(JUNIT_XML)
|
||||||
|
assert junit_xml.getroot().tag == 'testsuites'
|
||||||
|
testsuites = junit_xml.findall("./testsuite")
|
||||||
|
testcases_gl = junit_xml.findall("./testsuite[@name='traces.yml:gl-test-device']/testcase")
|
||||||
|
testcases_vk = junit_xml.findall("./testsuite[@name='traces.yml:vk-test-device']/testcase")
|
||||||
|
|
||||||
|
assert len(testsuites) == 2
|
||||||
|
assert len(testcases_gl) == 1
|
||||||
|
assert len(testcases_vk) == 1
|
||||||
|
assert testcases_gl[0].get("name") == "trace1/magenta.testtrace"
|
||||||
|
assert testcases_gl[0].get("classname") == "traces.yml:gl-test-device"
|
||||||
|
assert testcases_vk[0].get("name") == "trace2/olive.testtrace"
|
||||||
|
assert testcases_vk[0].get("classname") == "traces.yml:vk-test-device"
|
||||||
|
|
||||||
|
def test_tracie_writes_dashboard_url_in_junit_xml_failure_tag():
|
||||||
|
filename = "./tests/traces.yml"
|
||||||
|
content = read_from(filename)
|
||||||
|
content = content.replace("5efda83854befe0155ff8517a58d5b51",
|
||||||
|
"8e0a801367e1714463475a824dab363b")
|
||||||
|
write_to(content, filename)
|
||||||
|
|
||||||
|
assert not run_tracie()
|
||||||
|
|
||||||
|
junit_xml = ET.parse(JUNIT_XML)
|
||||||
|
failures_gl = junit_xml.findall("./testsuite[@name='traces.yml:gl-test-device']/testcase/failure")
|
||||||
|
failures_vk = junit_xml.findall("./testsuite[@name='traces.yml:vk-test-device']/testcase/failure")
|
||||||
|
|
||||||
|
assert len(failures_gl) == 0
|
||||||
|
assert len(failures_vk) == 1
|
||||||
|
dashboard_url = "https://tracie.freedesktop.org/dashboard/imagediff/test-project/42/trace2/olive.testtrace"
|
||||||
|
assert dashboard_url in failures_vk[0].text
|
||||||
|
@@ -138,6 +138,12 @@ def ensure_reference_image(file_name, checksum):
|
|||||||
return
|
return
|
||||||
upload_to_minio(file_name, resource, 'image/png')
|
upload_to_minio(file_name, resource, 'image/png')
|
||||||
|
|
||||||
|
def image_diff_url(trace_path):
|
||||||
|
return "%s/imagediff/%s/%s/%s" % (DASHBOARD_URL,
|
||||||
|
os.environ.get('CI_PROJECT_PATH'),
|
||||||
|
os.environ.get('CI_JOB_ID'),
|
||||||
|
trace_path)
|
||||||
|
|
||||||
def gitlab_check_trace(project_url, device_name, trace, expectation):
|
def gitlab_check_trace(project_url, device_name, trace, expectation):
|
||||||
gitlab_ensure_trace(project_url, trace)
|
gitlab_ensure_trace(project_url, trace)
|
||||||
|
|
||||||
@@ -158,11 +164,7 @@ def gitlab_check_trace(project_url, device_name, trace, expectation):
|
|||||||
(trace['path'], expectation['checksum'], checksum))
|
(trace['path'], expectation['checksum'], checksum))
|
||||||
print("[check_image] For more information see "
|
print("[check_image] For more information see "
|
||||||
"https://gitlab.freedesktop.org/mesa/mesa/blob/master/.gitlab-ci/tracie/README.md")
|
"https://gitlab.freedesktop.org/mesa/mesa/blob/master/.gitlab-ci/tracie/README.md")
|
||||||
image_diff_url = "%s/imagediff/%s/%s/%s" % (DASHBOARD_URL,
|
print("[check_image] %s" % image_diff_url(trace['path']))
|
||||||
os.environ['CI_PROJECT_PATH'],
|
|
||||||
os.environ['CI_JOB_ID'],
|
|
||||||
trace['path'])
|
|
||||||
print("[check_image] %s" % image_diff_url)
|
|
||||||
ok = False
|
ok = False
|
||||||
|
|
||||||
trace_dir = os.path.split(trace['path'])[0]
|
trace_dir = os.path.split(trace['path'])[0]
|
||||||
@@ -185,6 +187,39 @@ def gitlab_check_trace(project_url, device_name, trace, expectation):
|
|||||||
|
|
||||||
return ok, result
|
return ok, result
|
||||||
|
|
||||||
|
def write_junit_xml(junit_xml_path, traces_filename, device_name, results):
|
||||||
|
tests = len(results)
|
||||||
|
failures = sum(1 for r in results.values() if r["actual"] != r["expected"])
|
||||||
|
|
||||||
|
try:
|
||||||
|
testsuites = ET.parse(junit_xml_path).getroot()
|
||||||
|
except:
|
||||||
|
test_name = os.environ.get('CI_PROJECT_PATH') + "/" + \
|
||||||
|
os.environ.get('CI_PIPELINE_ID') + "/" + \
|
||||||
|
os.environ.get('CI_JOB_ID')
|
||||||
|
testsuites = ET.Element('testsuites', name=test_name)
|
||||||
|
|
||||||
|
testsuites.set('tests', str(int(testsuites.get('tests', 0)) + tests))
|
||||||
|
testsuites.set('failures', str(int(testsuites.get('failures', 0)) + failures))
|
||||||
|
|
||||||
|
testsuite_name = os.path.basename(traces_filename) + ":" + device_name
|
||||||
|
|
||||||
|
testsuite = ET.SubElement(testsuites, 'testsuite',
|
||||||
|
name=testsuite_name,
|
||||||
|
tests=str(tests), failures=str(failures))
|
||||||
|
|
||||||
|
for (path, result) in results.items():
|
||||||
|
testcase = ET.SubElement(testsuite, 'testcase', name=path,
|
||||||
|
classname=testsuite_name)
|
||||||
|
if result["actual"] != result["expected"]:
|
||||||
|
failure = ET.SubElement(testcase, 'failure')
|
||||||
|
failure.text = \
|
||||||
|
("Images differ (expected: %s, actual: %s).\n" + \
|
||||||
|
"To view the image differences visit:\n%s") % \
|
||||||
|
(result["expected"], result["actual"], image_diff_url(path))
|
||||||
|
|
||||||
|
ET.ElementTree(testsuites).write(junit_xml_path)
|
||||||
|
|
||||||
def run(filename, device_name):
|
def run(filename, device_name):
|
||||||
|
|
||||||
with open(filename, 'r') as f:
|
with open(filename, 'r') as f:
|
||||||
@@ -210,8 +245,13 @@ def run(filename, device_name):
|
|||||||
os.makedirs(RESULTS_PATH, exist_ok=True)
|
os.makedirs(RESULTS_PATH, exist_ok=True)
|
||||||
with open(os.path.join(RESULTS_PATH, 'results.yml'), 'w') as f:
|
with open(os.path.join(RESULTS_PATH, 'results.yml'), 'w') as f:
|
||||||
yaml.safe_dump(results, f, default_flow_style=False)
|
yaml.safe_dump(results, f, default_flow_style=False)
|
||||||
|
|
||||||
|
junit_xml_path = os.path.join(RESULTS_PATH, "junit.xml")
|
||||||
|
write_junit_xml(junit_xml_path, filename, device_name, results)
|
||||||
|
|
||||||
if os.environ.get('TRACIE_UPLOAD_TO_MINIO', '0') == '1':
|
if os.environ.get('TRACIE_UPLOAD_TO_MINIO', '0') == '1':
|
||||||
upload_artifact(os.path.join(RESULTS_PATH, 'results.yml'), 'traces/results.yml', 'text/yaml')
|
upload_artifact(os.path.join(RESULTS_PATH, 'results.yml'), 'traces/results.yml', 'text/yaml')
|
||||||
|
upload_artifact(junit_xml_path, 'traces/junit.xml', 'text/xml')
|
||||||
|
|
||||||
return all_ok
|
return all_ok
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user