Search code examples
c#seleniumnunitextentreports

show only the last test


I'm using ExtentReport as my reporter in Selenium\Appium. When a test finishes, I'm using the TearDown and OneTimeTearDown as follow.

[TearDown]
    public void CloseDriver()
    {
        var status = TestContext.CurrentContext.Result.Outcome.Status;
        var stackTrace = "<pre>" + TestContext.CurrentContext.Result.Message + "</pre>";
        var errorMessage = TestContext.CurrentContext.Result.Message;
        if (status == NUnit.Framework.Interfaces.TestStatus.Failed)
        {
            test.Log(LogStatus.Fail, status + errorMessage);
            var ScreenShotPath = Utils.TakeScreenShot(_webdriver);
            test.Log(LogStatus.Fail, "Screen Shot Below: " + test.AddScreenCapture(ScreenShotPath));
        }
        else if (status == NUnit.Framework.Interfaces.TestStatus.Passed)
        {
            test.Log(LogStatus.Pass, status + errorMessage);
        }
        extent.EndTest(test);
       _webdriver.Quit();

        Utils.KilliExplore();
    }
[OneTimeTearDown]
    public void OneTimeTearDown()
    {
        Utils.KillIEDriver();
        extent.Flush();
        extent.Close();
    }

Lately I added an extension method which extends the Nunit's Retry attribiute. That's my code of the extension. (That's the source by the way: https://testingrepository.com/retry-failed-tests-in-nunit/)

public class CustomRetry : PropertyAttribute, IWrapSetUpTearDown
{
    private int _count;
    public CustomRetry(int count) : base(count)
    {
        _count = count;
    }

    #region IWrapSetUpTearDown Members

    public TestCommand Wrap(TestCommand command)
    {
        return new CustomRetryCommand(command, _count);
    }

    #endregion

    #region Nested CustomRetry Class

    /// <summary>
    /// The test command for the RetryAttribute
    /// </summary>
    public class CustomRetryCommand : DelegatingTestCommand
    {
        private int _retryCount;

        /// <summary>
        /// Initializes a new instance of the <see cref="CustomRetryCommand"/> class.
        /// </summary>
        /// <param name="innerCommand">The inner command.</param>
        /// <param name="retryCount">The number of repetitions</param>
        public CustomRetryCommand(TestCommand innerCommand, int retryCount)
            : base(innerCommand)
        {
            _retryCount = retryCount;
        }

        /// <summary>
        /// Runs the test, saving a TestResult in the supplied TestExecutionContext.
        /// </summary>
        /// <param name="context">The context in which the test should run.</param>
        /// <returns>A TestResult</returns>
        public override TestResult Execute(TestExecutionContext context)
        {
            int count = _retryCount;

            while (count-- > 0)
            {
                context.CurrentResult = innerCommand.Execute(context);
                var results = context.CurrentResult.ResultState;

                if (results != ResultState.Error
                    && results != ResultState.Failure
                    && results != ResultState.SetUpError
                    && results != ResultState.SetUpFailure
                    && results != ResultState.TearDownError
                    && results != ResultState.ChildFailure)
                {
                    break;
                }
            }

            return context.CurrentResult;
        }
    }

    #endregion
}

When I'm setting the number of CustomeRetry attribute as 3(e.g) , if a test fails two times and passed on the 3rd time, then the ExtentReport will show 3 tests , what I would like to see is the last one for each test\testcase. If a test ran just once then I'm good , but as for my example, I just want to see this test as passed. If a tests fails 3 times , then just one row of this test, and marked as fail. Any suggestion how to do that?


Solution

  • I'm answering this without a lot of knowledge of ExtentReport, but the problem appears pretty clear, so here goes...

    Since your custom wrapper wraps SetUp and TearDown, the TearDown method is run up to three times. In the Teardown, you call extent.EndTest(), so that is called up to three times. I imagine that's why your test appears three times in the report.

    Depending on what you want to happen, there are two solutions.

    1. Remove the code from your TearDown that you do not want to have executed for each retry and put it into your wrapper.

    2. Use a condition based on the test result to decide whether to execute the code that should only execute the last time.

    3. Modify your wrapper so that it only wraps the test method. If you do this, remember that you will only get a single call to SetUp and TearDown for the method.