e2etest/GuestProxyAgentTest/Utilities/JUnitTestResultBuilder.cs (167 lines of code) (raw):

// Copyright (c) Microsoft Corporation // SPDX-License-Identifier: MIT using System.Net; using System.Xml; namespace GuestProxyAgentTest.Utilities { /// <summary> /// JUnit test result builder /// </summary> public class JunitTestResultBuilder { // key is test suit name, value is junit-doc, junit-suite // azure public publish test result task doesn't display result correctly, if result has multiple test suites // work around is create one result file per test suite (test scenario in E2E) private readonly Dictionary<string, (XmlDocument, XmlElement)> testSuiteMap = new Dictionary<string, (XmlDocument, XmlElement)>(); private readonly string testGroupName = null!; private readonly string testResultGroupFolder = null!; internal string testResultFolder = null!; public JunitTestResultBuilder(string testResultFolder, string testGroupName) { this.testGroupName = testGroupName; this.testResultGroupFolder = Path.Combine(testResultFolder, testGroupName); Directory.CreateDirectory(this.testResultGroupFolder); this.testResultFolder = testResultFolder; } /// <summary> /// Add success test result, it will merge stdoutput with customoutput. /// </summary> /// <param name="testScenarioName"></param> /// <param name="testName"></param> /// <param name="stdOut"></param> /// <param name="customOut"></param> /// <returns></returns> public JunitTestResultBuilder AddSuccessTestResult(string testScenarioName, string testName, string stdOut, string customOut, long durationInMilliseconds = 0) { var stdOutMessage = "Std output:" + Environment.NewLine + stdOut + Environment.NewLine + "Custom output:" + Environment.NewLine + customOut; return AddSuccessTestResult(testScenarioName, testName, stdOutMessage, durationInMilliseconds); } /// <summary> /// Add succeed test result /// </summary> /// <param name="testScenarioName"></param> /// <param name="testName"></param> /// <param name="stdOutMessage"></param> /// <returns></returns> public JunitTestResultBuilder AddSuccessTestResult(string testScenarioName, string testName, string stdOutMessage, long durationInMilliseconds = 0) { lock (this) { XmlDocument doc = null!; if (!testSuiteMap.ContainsKey(testScenarioName)) { doc = new XmlDocument(); var testsuites = doc.CreateElement("testsuites"); doc.AppendChild(testsuites); XmlElement testSuiteElement = doc.CreateElement("testsuite"); testSuiteElement.SetAttribute("name", testGroupName + "." + testScenarioName); testSuiteElement.SetAttribute("tests", "0"); testSuiteElement.SetAttribute("errors", "0"); testSuiteElement.SetAttribute("failures", "0"); testSuiteElement.SetAttribute("skipped", "0"); testSuiteElement.SetAttribute("timestamp", DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss")); testsuites.AppendChild(testSuiteElement); testSuiteMap[testScenarioName] = (doc, testSuiteElement); } doc = testSuiteMap[testScenarioName].Item1; var testSuite = testSuiteMap[testScenarioName].Item2; testSuite.SetAttribute("tests", StringAdd(testSuite.GetAttribute("tests"), 1)); XmlElement successTestCaseElement = doc.CreateElement("testcase"); successTestCaseElement.SetAttribute("name", testName); successTestCaseElement.SetAttribute("classname", testGroupName + "." + testScenarioName); successTestCaseElement.SetAttribute("time", ((double)durationInMilliseconds / 1000).ToString()); testSuite.AppendChild(successTestCaseElement); XmlElement systemOutElement = doc.CreateElement("system-out"); systemOutElement.InnerText = stdOutMessage; successTestCaseElement.AppendChild(systemOutElement); } return this; } /// <summary> /// Add failure test result /// </summary> /// <param name="testScenarioName"></param> /// <param name="testName"></param> /// <param name="stdOutMessage"></param> /// <param name="stdErrMessage"></param> /// <param name="customOutput"></param> /// <returns></returns> public JunitTestResultBuilder AddFailureTestResult(string testScenarioName, string testName, string stdOutMessage, string stdErrMessage, string customOutput, long durationInMilliseconds = 0) { lock (this) { XmlDocument doc = null!; if (!testSuiteMap.ContainsKey(testScenarioName)) { doc = new XmlDocument(); var testsuites = doc.CreateElement("testsuites"); doc.AppendChild(testsuites); XmlElement testSuiteElement = doc.CreateElement("testsuite"); testSuiteElement.SetAttribute("name", testGroupName + "." + testScenarioName); testSuiteElement.SetAttribute("tests", "0"); testSuiteElement.SetAttribute("errors", "0"); testSuiteElement.SetAttribute("failures", "0"); testSuiteElement.SetAttribute("skipped", "0"); testSuiteElement.SetAttribute("timestamp", DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss")); testsuites.AppendChild(testSuiteElement); testSuiteMap[testScenarioName] = (doc, testSuiteElement); } doc = testSuiteMap[testScenarioName].Item1; var testSuite = testSuiteMap[testScenarioName].Item2; testSuite.SetAttribute("tests", StringAdd(testSuite.GetAttribute("tests"), 1)); testSuite.SetAttribute("failures", StringAdd(testSuite.GetAttribute("failures"), 1)); XmlElement failedTestCaseElement = doc.CreateElement("testcase"); failedTestCaseElement.SetAttribute("name", testName); failedTestCaseElement.SetAttribute("classname", testGroupName + "." + testScenarioName); failedTestCaseElement.SetAttribute("time", ((double)durationInMilliseconds / 1000).ToString()); testSuite.AppendChild(failedTestCaseElement); XmlElement systemOutElement = doc.CreateElement("system-out"); systemOutElement.InnerText = stdOutMessage; failedTestCaseElement.AppendChild(systemOutElement); XmlElement systemErrElement = doc.CreateElement("system-err"); systemErrElement.InnerText = stdErrMessage; failedTestCaseElement.AppendChild(systemErrElement); XmlElement failureElement = doc.CreateElement("failure"); failureElement.SetAttribute("message", "Std Error Output: " + Environment.NewLine + stdErrMessage + Environment.NewLine + Environment.NewLine + "Custom output: " + Environment.NewLine + customOutput); failureElement.SetAttribute("type", "AssertionException"); failedTestCaseElement.AppendChild(failureElement); } return this; } public JunitTestResultBuilder AddAbortedTestResult(string testScenarioName, string testName, string message) { lock (this) { XmlDocument doc = null!; if (!testSuiteMap.ContainsKey(testScenarioName)) { doc = new XmlDocument(); var testsuites = doc.CreateElement("testsuites"); doc.AppendChild(testsuites); XmlElement testSuiteElement = doc.CreateElement("testsuite"); testSuiteElement.SetAttribute("name", testGroupName + "." + testScenarioName); testSuiteElement.SetAttribute("tests", "0"); testSuiteElement.SetAttribute("errors", "0"); testSuiteElement.SetAttribute("failures", "0"); testSuiteElement.SetAttribute("skipped", "0"); testSuiteElement.SetAttribute("timestamp", DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss")); testsuites.AppendChild(testSuiteElement); testSuiteMap[testScenarioName] = (doc, testSuiteElement); } doc = testSuiteMap[testScenarioName].Item1; var testSuite = testSuiteMap[testScenarioName].Item2; testSuite.SetAttribute("tests", StringAdd(testSuite.GetAttribute("tests"), 1)); testSuite.SetAttribute("skipped", StringAdd(testSuite.GetAttribute("skipped"), 1)); XmlElement abortedTestCaseElement = doc.CreateElement("testcase"); abortedTestCaseElement.SetAttribute("name", testName); abortedTestCaseElement.SetAttribute("classname", testGroupName + "." + testScenarioName); abortedTestCaseElement.SetAttribute("time", "0"); testSuite.AppendChild(abortedTestCaseElement); XmlElement abortedElement = doc.CreateElement("skipped"); abortedElement.SetAttribute("message", "Test case aborted."); abortedElement.InnerText = message; abortedTestCaseElement.AppendChild(abortedElement); } return this; } /// <summary> /// build and save the test result to file /// </summary> /// <returns></returns> public List<string> Build() { List<string> result = new List<string>(); foreach (KeyValuePair<string, (XmlDocument, XmlElement)> kv in testSuiteMap) { var doc = kv.Value.Item1; var resultPath = Path.Combine(this.testResultGroupFolder, kv.Key + "-TestResults.xml"); result.Add(resultPath); doc.Save(resultPath); } return result; } private string StringAdd(string str, int added) { var val = int.Parse(str) + added; return val + ""; } } }