I have our test suite run and generate both the original Ranorex report and the Junit/XML report, then run this utility to parse the XML report and write a summary to an HTM file. Next, I run this freeware SendItQuiet utility to grab the HTM file as the email body and distribute the email. The report looks like the abbreviated screenshot below.
Code: Select all
using System;
using System.Xml;
namespace RanorexResultUploader
{
class Program
{
/// <summary>
/// Reads and parses the Ranorex XML/JUnit report to get stats for overall test suite execution and
/// individual test case results, then writes this information to an HTM file to be included in the
/// body of the results email (a subsequent call to the SendItQuiet email utility grabs the file).
/// </summary>
/// <param name="args">
/// [0] - The original Ranorex report file, e.g.: HOSTNAME_YYYY_MM_DD_HH_NN_SUITENAME.rxlog
/// [1] - The build number of the installed AUT, e.g.: 1.4.2.32
/// </param>
static void Main(string[] args)
{
XmlDocument resultsFile = new XmlDocument();
#if DEBUG
// For local debugging (replace with actual file)
string reportFile = @"\\<share>\<hostname>_2018_01_22_9_09_SelectedTest.rxlog";
string buildNumber = "1.4.2.X";
resultsFile.Load(reportFile + ".junit.xml");
#endif
// ********************************
#if !DEBUG
// For Release -- run-time parameters
string reportFile = args[0];
string buildNumber = args[1];
resultsFile.Load(@"C:\Test\Reports\" + reportFile + ".junit.xml");
#endif
using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"C:\Test\Reports\EmailBody.htm"))
{
TestSuite currentTestSuite = new TestSuite();
XmlNode testSuite = resultsFile.DocumentElement;
currentTestSuite.Name = testSuite.Attributes["name"].Value;
currentTestSuite.TestsRun = testSuite.Attributes["tests"].Value;
currentTestSuite.Failures = testSuite.Attributes["failures"].Value;
currentTestSuite.ExecutionTime = testSuite.Attributes["time"].Value;
currentTestSuite.Skipped = testSuite.Attributes["skipped"].Value;
currentTestSuite.TimeStamp = testSuite.Attributes["timestamp"].Value;
currentTestSuite.HostName = testSuite.Attributes["hostname"].Value;
file.WriteLine("<table border=\"1\">");
file.WriteLine("<caption><b>{0}</b></caption>", currentTestSuite.Name);
file.WriteLine("<tr><th>Build<td>{0}", buildNumber);
file.WriteLine("<tr><th>Tests Run<td>{0}", currentTestSuite.TestsRun);
if (currentTestSuite.Failures != "0")
file.WriteLine("<tr><th>Failed<td bgcolor=\"Red\">{0}", currentTestSuite.Failures);
else
file.WriteLine("<tr><th>Failed<td bgcolor=\"Lime\">0");
if (currentTestSuite.Skipped != "0")
file.WriteLine("<tr><th>Skipped<td bgcolor=\"Yellow\">{0}", currentTestSuite.Skipped);
else
file.WriteLine("<tr><th>Skipped<td>0");
file.WriteLine("<tr><th>Execution Time<td>{0}", currentTestSuite.ExecutionTime);
file.WriteLine("<tr><th>Timestamp<td>{0}", currentTestSuite.TimeStamp);
file.WriteLine("<tr><th>Host<td>{0}", currentTestSuite.HostName);
file.WriteLine("</table><br>");
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine("Test Suite:");
Console.WriteLine("\tName: {0}", currentTestSuite.Name);
Console.WriteLine("\tTests Run: {0}", currentTestSuite.TestsRun);
Console.WriteLine("\tFailures: {0}", currentTestSuite.Failures);
Console.WriteLine("\tTests Skipped: {0}", currentTestSuite.Skipped);
Console.WriteLine("\tExecution Time: {0}", currentTestSuite.ExecutionTime);
Console.WriteLine();
file.WriteLine("<table border=\"1\">");
file.WriteLine("<tr><th>Test Case<th>Result<th>Duration<th>Error Msg");
XmlNodeList testCases = resultsFile.DocumentElement.SelectNodes("/testsuite/testcase");
foreach (XmlNode currentNode in testCases)
{
TestCase testCase = new TestCase();
testCase.Name = currentNode.Attributes["name"].Value;
testCase.ExecutionTime = currentNode.Attributes["time"].Value;
testCase.ClassName = currentNode.Attributes["classname"].Value;
XmlNode skippedNode = currentNode.SelectSingleNode("skipped");
if (skippedNode != null)
{
testCase.SkippedMsg = skippedNode.Attributes["message"].Value;
}
XmlNode errorNode = currentNode.SelectSingleNode("error");
if (errorNode != null)
{
testCase.ErrorMsg = errorNode.Attributes["message"].Value;
XmlNode errorDesc = currentNode.SelectSingleNode("system-err");
if (errorDesc != null)
{
if (errorDesc.InnerText.Length > 1000)
testCase.ErrorDescription = errorDesc.InnerText.Substring(0, 1000);
else
testCase.ErrorDescription = errorDesc.InnerText;
}
}
Console.WriteLine("Test Case: {0}", testCase.Name);
Console.WriteLine("\tTime: {0}", testCase.ExecutionTime);
file.Write("<tr><td>{0}", testCase.Name);
if (testCase.Failed)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("\tFailed: {0}", testCase.ErrorMsg);
Console.WriteLine(testCase.ErrorDescription);
file.Write("<td bgcolor=\"Red\">FAILED");
}
else if (testCase.Skipped)
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("\tSkipped: {0}", testCase.SkippedMsg);
file.Write("<td bgcolor=\"Yellow\">SKIPPED");
}
else
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("\tPASSED!");
file.Write("<td bgcolor=\"Lime\">PASSED");
}
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine();
file.Write("<td>{0}", testCase.ExecutionTime);
file.Write("<td>{0}", testCase.ErrorDescription);
file.WriteLine();
}
file.WriteLine("</table>");
file.WriteLine("<br><br>Complete Log File at:<br>");
file.WriteLine(@"\\{0}\Reports\{1}", currentTestSuite.HostName, reportFile);
file.WriteLine("</html></body>");
}
#if DEBUG
Console.ReadLine();
#endif
}
}
class TestCase
{
public string Name;
public string ClassName;
public bool Skipped;
private string _skippedMsg;
public string SkippedMsg
{
get { return _skippedMsg; }
set
{
Skipped = true;
_skippedMsg = value;
}
}
public bool Failed;
private string _errorMsg = "";
public string ErrorMsg
{
get { return _errorMsg;}
set
{
Failed = true;
_errorMsg = value;
}
}
private string _errorDescription = "";
public string ErrorDescription
{
get { return _errorDescription; }
set
{
Failed = true;
_errorDescription = value;
}
}
public string ExecutionTime
{
get
{
int hours = _executionInSeconds / 3600;
int minutes = (_executionInSeconds % 3600) / 60;
int seconds = (_executionInSeconds % 3600) % 60;
string returnValue = (hours > 0 ? hours.ToString() + "h " : "") + minutes.ToString() + "m " + seconds.ToString() + "s";
return returnValue;
}
set { _executionInSeconds = Int32.Parse(value); }
}
private int _executionInSeconds = 0;
public TestCase()
{
Skipped = false;
Failed = false;
}
}
class TestSuite
{
public string Name;
public string TestsRun;
public string Failures;
public string Skipped;
public string TimeStamp;
public string HostName;
public string ExecutionTime
{
get
{
int hours = _executionInSeconds / 3600;
int minutes = (_executionInSeconds % 3600) / 60;
int seconds = (_executionInSeconds % 3600) % 60;
string returnValue = (hours > 0 ? hours.ToString() + "h " : "") + minutes.ToString() + "m " + seconds.ToString() + "s";
return returnValue;
}
set { _executionInSeconds = Int32.Parse(value); }
}
private int _executionInSeconds = 0;
}
}
Code: Select all
call \Test\SendItQuiet\SendItQuiet.exe -s <sender> -port <port> -u %fromEmail% -protocol normal -p -f %fromEmail% -t %recipientList% -subject %emailSubject% -bodyfile %baseReportPath%\EmailBody.htm