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

Missing detailed test results with a XML file ( but not the other) #159

Open
WindingWinter opened this issue Dec 1, 2022 · 1 comment
Open

Comments

@WindingWinter
Copy link

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:

Nunit3mits2testresult

Nunit3sidetestresult

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

@RuanAlesi
Copy link

I have the same issue here:
image
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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants