anshooarora / extentreports-csharp

Community version of Extent API for .NET has moved to https://github.com/extent-framework/
http://extentreports.com/
Other
47 stars 43 forks source link

Not all test reports are displayed when running tests in parallel #46

Closed kpmck closed 7 years ago

kpmck commented 7 years ago

Hello,

I am currently running parallel tests with NUnit v 3.6.1, and at the end of the tests when the report is generated, I notice I am sometimes missing some of the tests being reported. Currently I am still using ExtentReports v2.41.0, but have also attempted using v.3.0.1 with the same issue.

Below is how I am initializing my Extent Reports in the setup/teardown methods, which are all called prior to every test. I have eliminated extraneous code from the below example to only focus on the Extent Reports implementation:

        public string testname;
        public ExtentReports rep;
        public ExtentTest test;

        [OneTimeSetUp]
        public void OneTimeSetup()
        {
            rep = ExtentManager.getInstance();
        }

        [SetUp]
        public void Setup()
        {
            testname = TestContext.CurrentContext.Test.Name;
            test = rep.StartTest(testname);
            test.Log(LogStatus.Info, "Beginning the test: " + testname);
        }

        [TearDown]
        public void TearDown()
        {
            var status = TestContext.CurrentContext.Result.Outcome.Status;
            var stackTrace = TestContext.CurrentContext.Result.StackTrace;
            var errorMessage = TestContext.CurrentContext.Result.Message;

            if (status == TestStatus.Failed)
            {
                test.Log(LogStatus.Fail, "Ending the test " + testname + " with the status FAILED.");
                test.Log(LogStatus.Fail, "Error Message: " + errorMessage);
                test.Log(LogStatus.Fail, "Stack Trace: " + stackTrace);
            }
            else
            {
                test.Log(LogStatus.Pass, "Ending the test " + testname + " with the status PASSED.");
            }
            rep.EndTest(test);
        }

        [OneTimeTearDown]
        public void OneTimeTearDown()
        {
            rep.Flush();
        }

And below is the ExtentManager class being initialized:

    public class ExtentManager
    {
        public static String rootFolder = Constants.ROOT_FOLDER_FRAMEWORK + "\\Reporting";
        public ExtentManager()
        {

        }

        private static ExtentReports extent;

        public static ExtentReports getInstance()
        {
            if (extent == null)
            {
                string filename = DateTime.Now.ToString().Replace("-", "_").Replace(":", "_").Replace(" ", "_").Replace("/", "_").Replace("\\", "_") + ".html";
                extent = new ExtentReports(Constants.REPORT_PATH + filename, true);

                string teststr = rootFolder;
                extent.LoadConfig(rootFolder + "//extent-config.xml");

            }
            return extent;
        }
}

Any ideas as to what could be causing some tests to now show up in my final report?

Thank you in advance!

anshooarora commented 7 years ago

That may be because your instances of ExtentTest test in the base class are being overwritten each time? These can be ThreadLocal if multiple threads are going to access it or you can create a manager class that manages providing your test instance to each thread.

See ExtentTestManager here. This is for Java/TestNG but the .NET implementation can be very similar.

kpmck commented 7 years ago

Thank you very much for your quick reply! Are there any examples as to how to make the instances of ExtentTest ThreadLocal that I could reference? I am fairly new to management of test threads and while I have been trying to sort out a solution for this particular issue for a while, I seem to be getting nowhere fast.

On Tue, Mar 28, 2017 at 5:33 PM, Anshoo Arora notifications@github.com wrote:

That may be because your instances of ExtentTest test in the base class are being overwritten each time? These can be ThreadLocal if multiple threads are going to access it or you can create a manager class that manages providing your test instance to each thread.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/anshooarora/extentreports-csharp/issues/46#issuecomment-289911736, or mute the thread https://github.com/notifications/unsubscribe-auth/AZBEVfs_cSXm9ionYSvx2z8cMaCRkdBJks5rqXy_gaJpZM4MsOAF .

anshooarora commented 7 years ago

See if this helps:

public class ExtentTestManager
{
    private static ThreadLocal<ExtentTest> _test;
    private static ExtentReports _extent = ExtentManager.Instance;

    public static ExtentTest GetTest()
    {
        return _test.Value;
    }

    public static ExtentTest CreateTest(string name)
    {
        if (_test == null)
            _test = new ThreadLocal<ExtentTest>();

        var t = _extent.CreateTest(name);
        _test.Value = t;

        return t;
    }
}

public class ExtentManager
{
    private static readonly ExtentReports _instance = new ExtentReports();

    static ExtentManager()
    {
        var htmlReporter = new ExtentHtmlReporter("Extent.html");
        Instance.AttachReporter(htmlReporter);
    }

    private ExtentManager() { }

    public static ExtentReports Instance
    {
        get
        {
            return _instance;
        }
    }
}

Usage:

// create test and log
ExtentTestManager.CreateTest("HelloWorld");
ExtentTestManager.GetTest().Pass("Pass");
kpmck commented 7 years ago

That was perfect and resolved the issue. Thank you very much, I greatly appreciate your help! For posterity, I've included my updated code below (with extraneous code removed to only display Extent Reporting) with your solution implemented:

    public class SetupTeardown
    {
        public string testname;
        public ExtentTest test;
        public ExtentReports rep;

        [OneTimeSetUp]
        public void OneTimeSetup()
        {
            rep = ExtentManager.Instance;
        }

        [SetUp]
        public void Setup()
        {
            testname = TestContext.CurrentContext.Test.Name;
            testname = testname.Remove(testname.IndexOf('('), testname.Length - testname.IndexOf('('));
            test = rep.CreateTest(testname);
            test.Log(Status.Info, "Starting the test " + testname + "...");
        }

        [TearDown]
        public void TearDown()
        {
            var status = TestContext.CurrentContext.Result.Outcome.Status;
            var stackTrace = TestContext.CurrentContext.Result.StackTrace;
            var errorMessage = TestContext.CurrentContext.Result.Message;

            if (status == TestStatus.Failed)
            {
                test.Log(Status.Fail, "Ending the test " + testname + " with the status FAILED.");
                test.Log(Status.Fail, "Error Message: " + errorMessage);
                test.Log(Status.Fail, "Stack Trace: " + stackTrace);
            }
            else
            {
                test.Log(Status.Pass, "Ending the test " + testname + " with the status PASSED.");
            }
        }

        [OneTimeTearDown]
        public void OneTimeTearDown()
        {
            rep.Flush();
        }

    public class ExtentManager
    {
        private static readonly ExtentReports _instance = new ExtentReports();

        static ExtentManager()
        {
            var htmlReporter = new ExtentHtmlReporter(*YOURREPORTPATH/FILENAME HERE*);
            Instance.AttachReporter(htmlReporter);
        }

        private ExtentManager() { }

        public static ExtentReports Instance
        {
            get
            {
                return _instance;
            }
        }
    }

    public class ExtentTestManager
    {
        private static ThreadLocal<ExtentTest> _test;
        private static ExtentReports _extent = ExtentManager.Instance;

        public static ExtentTest GetTest()
        {
            return _test.Value;
        }

        public static ExtentTest CreateTest(string name)
        {
            if (_test == null)
                _test = new ThreadLocal<ExtentTest>();

            var t = _extent.CreateTest(name);
            _test.Value = t;

            return t;
        }

        private static ExtentHtmlReporter getHtmlReporter()
        {
            ExtentHtmlReporter htmlReporter = new ExtentHtmlReporter(ExtentManager.rootFolder);

            htmlReporter.Configuration().ChartVisibilityOnOpen = true;

            String documentTitle = "ExtentReports 3.0";
            htmlReporter.Configuration().DocumentTitle = documentTitle;

            String encoding = "UTF-8";
            htmlReporter.Configuration().Encoding = encoding;

            htmlReporter.Configuration().Protocol = Protocol.HTTPS;

            String reportName = "ExtentReports";
            htmlReporter.Configuration().ReportName = reportName;

            htmlReporter.Configuration().ChartLocation = ChartLocation.Top;

            htmlReporter.Configuration().Theme = Theme.Standard;

            return htmlReporter;
        }
}
anshooarora commented 7 years ago

Glad it works now.