extentreports-csharp
extentreports-csharp copied to clipboard
Missing detailed test results with a XML file ( but not the other)
I've tested this in ExtentReports 4.1.0.0
For some reason, the ExtentReports is missing detailed test results with one XML (Nunit3mits2testresult.xml), but not the other (Nunit3sidetestresult.xml).
Here are the screenshots, notice the glaring difference in the RHS panels:
Here's my code:
/// <summary>
///
/// </summary>
/// <param name="testResultsFilePath">The XML file</param>
/// <param name="htmlDirectory">Folder path</param>
/// <returns></returns>
public void ProcessSingle(string testResultsFilePath, string htmlDirectory)
{
var _extent = new ExtentReports();
var output = htmlDirectory.EndsWith("\\") || htmlDirectory.EndsWith("/") ? htmlDirectory : htmlDirectory + "\\";
_extent.AttachReporter(new ExtentHtmlReporter(output));
new NUnitParser(_extent).ParseTestRunnerOutput(testResultsFilePath);
_extent.Flush();
}
internal class NUnitParser
{
private ExtentReports _extent;
public NUnitParser(ExtentReports extent)
{
_extent = extent;
}
public void ParseTestRunnerOutput(string resultsFile)
{
var doc = XDocument.Load(resultsFile);
DateTime timeStampParsed;
if (doc.Root == null)
{
throw new NullReferenceException("Root element not found for " + resultsFile);
}
AddSystemInformation(doc);
var suites = doc
.Descendants("test-suite")
.Where(x => x.Attribute("type").Value.Equals("TestFixture", StringComparison.CurrentCultureIgnoreCase));
foreach (var ts in suites.ToList())
{
var test = _extent.CreateTest(ts.Attribute("name").Value);
// any error messages and/or stack-trace
var failure = ts.Element("failure");
if (failure != null)
{
var message = failure.Element("message");
if (message != null)
{
test.Fail(message.Value);
}
var stacktrace = failure.Element("stack-trace");
if (stacktrace != null && !string.IsNullOrWhiteSpace(stacktrace.Value))
{
test.Fail(MarkupHelper.CreateCodeBlock(stacktrace.Value));
}
}
var output = ts.Element("output")?.Value;
if (!string.IsNullOrWhiteSpace(output))
{
test.Info(output);
}
// get test suite level categories
var suiteCategories = ParseTags(ts, false);
// Test Cases
foreach (var tc in ts.Descendants("test-case").ToList())
{
var node = CreateNode(tc, test);
AssignStatusAndMessage(tc, node);
AssignTags(tc, node);
if (tc.Attribute("start-time") != null)
{
DateTime.TryParse(tc.Attribute("start-time").Value, out timeStampParsed);
node.Model.StartTime = timeStampParsed;
}
if (tc.Attribute("end-time") != null)
{
DateTime.TryParse(tc.Attribute("end-time").Value, out timeStampParsed);
node.Model.EndTime = timeStampParsed;
}
}
}
}
private static ExtentTest CreateNode(XElement tc, ExtentTest test)
{
var name = tc.Attribute("name").Value;
var descriptions =
tc.Descendants("property")
.Where(c => c.Attribute("name").Value.Equals("Description", StringComparison.CurrentCultureIgnoreCase));
var description = descriptions.Any() ? descriptions.ToArray()[0].Attribute("value").Value : string.Empty;
var node = test.CreateNode(name, description);
return node;
}
private static void AssignStatusAndMessage(XElement tc, ExtentTest test)
{
var status = StatusExtensions.ToStatus(tc.Attribute("result").Value);
// error and other status messages
var statusMessage = tc.Element("failure") != null && tc.Element("failure").Element("message") != null ? tc.Element("failure").Element("message").Value.Trim() : string.Empty;
statusMessage += tc.Element("failure") != null && tc.Element("failure").Element("stack-trace") != null ? tc.Element("failure").Element("stack-trace").Value.Trim() : string.Empty;
statusMessage += tc.Element("reason") != null && tc.Element("reason").Element("message") != null ? tc.Element("reason").Element("message").Value.Trim() : string.Empty;
statusMessage += tc.Element("output") != null ? tc.Element("output").Value.Trim() : string.Empty;
statusMessage = (status == Status.Fail || status == Status.Error) ? MarkupHelper.CreateCodeBlock(statusMessage).GetMarkup() : statusMessage;
statusMessage = string.IsNullOrEmpty(statusMessage) ? status.ToString() : statusMessage;
test.Log(status, statusMessage);
}
private static void AssignTags(XElement tc, ExtentTest test)
{
// get test case level categories
var categories = ParseTags(tc, true);
// if this is a parameterized test, get the categories from the parent test-suite
var parameterizedTestElement = tc
.Ancestors("test-suite").ToList()
.Where(x => x.Attribute("type").Value.Equals("ParameterizedTest", StringComparison.CurrentCultureIgnoreCase))
.FirstOrDefault();
if (null != parameterizedTestElement)
{
var paramCategories = ParseTags(parameterizedTestElement, false);
categories.UnionWith(paramCategories);
}
categories.ToList().ForEach(x => test.AssignCategory(x));
}
private static HashSet<string> ParseTags(XElement elem, bool allDescendents)
{
var parser = allDescendents
? new Func<XElement, string, IEnumerable<XElement>>((e, s) => e.Descendants(s))
: new Func<XElement, string, IEnumerable<XElement>>((e, s) => e.Elements(s));
var categories = new HashSet<string>();
if (parser(elem, "categories").Any())
{
var tags = parser(elem, "categories").Elements("category").ToList();
tags.ForEach(x => categories.Add(x.Attribute("name").Value));
}
return categories;
}
private void AddSystemInformation(XDocument doc)
{
if (doc.Descendants("environment") == null)
return;
var env = doc.Descendants("environment").FirstOrDefault();
if (env == null)
return;
if (env.Attribute("os-version") != null)
_extent.AddSystemInfo("NUnit Version", env.Attribute("os-version").Value);
if (env.Attribute("os-version") != null)
_extent.AddSystemInfo("OS Version", env.Attribute("os-version").Value);
if (env.Attribute("platform") != null)
_extent.AddSystemInfo("Platform", env.Attribute("platform").Value);
if (env.Attribute("clr-version") != null)
_extent.AddSystemInfo("CLR Version", env.Attribute("clr-version").Value);
if (env.Attribute("machine-name") != null)
_extent.AddSystemInfo("Machine Name", env.Attribute("machine-name").Value);
if (env.Attribute("user") != null)
_extent.AddSystemInfo("User", env.Attribute("user").Value);
if (env.Attribute("user-domain") != null)
_extent.AddSystemInfo("User Domain", env.Attribute("user-domain").Value);
}
}
Because the above code works with one XML but not the other, that's why I think it's a bug.
Here are the zip file that contains the above two XMLs. xml.zip
I have the same issue here:
These are the details:
- HTML Report
- Intermittent issue
- It happens more often on UI tests running in parallel with Playwright+Webkit
- Also the dashboard is empty