Search code examples
c#nunit.net-6.0specflowxamarin.uitest

is there a way to set the order for NUnit [OneTimeTearDown] test hook if more than one method has the hook?


I have a Mobile automation project that uses .NET 6 with Specflow, NUnit, and Xamarin.UITest. when my project was on .NET Framework 4.8 and I used the hook [OneTimeTearDown] I was able to make a console method that can generate the living doc using the code. See here for reference: https://github.com/SpecFlowOSS/SpecFlow/issues/2701 in .NET 6 I have an issue where when it generates the living doc but it's using the last run's TestExecution.json and not the run that has just been done. I found out that this is because the TestExecution.json is getting generated after [OneTimeTearDown] method that I have kicked off. This is due to Specflow NUnit using the same hook, see below:

// <auto-generated />
#pragma warning disable

using System.CodeDom.Compiler;
using System.Diagnostics;
using global::NUnit.Framework;
using global::TechTalk.SpecFlow;
using global::System.Runtime.CompilerServices;

[GeneratedCode("SpecFlow", "3.9.74")]
[SetUpFixture]
public class HEBPharmacy_UITests_NUnitAssemblyHooks
{
    [OneTimeSetUp]
    [MethodImpl(MethodImplOptions.NoInlining)]
    public void AssemblyInitialize()
    {
        var currentAssembly = typeof(HEBPharmacy_UITests_NUnitAssemblyHooks).Assembly;

        TestRunnerManager.OnTestRunStart(currentAssembly);
    }

    [OneTimeTearDown]
    [MethodImpl(MethodImplOptions.NoInlining)]
    public void AssemblyCleanup()
    {
        var currentAssembly = typeof(HEBPharmacy_UITests_NUnitAssemblyHooks).Assembly;

        TestRunnerManager.OnTestRunEnd(currentAssembly);
    }
}
#pragma warning restore

And here is my method:

[AfterTestRun]
[OneTimeTearDown]
public static void AfterTestRun()
{
    if (TestEnvironment.Platform.Equals(TestPlatform.Local))
    {
        Thread.Sleep(1000);
        GenerateLivingDoc();
    }
}

Keep in mind that the Specflow hook of [AfterTestRun] does not work on mac so it's not a solution. as you can see I have it on the method but it does not fix the issue. Is there a way to set the [OneTimeTearDown] hook so that my method kicks off after the one that Specflow has? and how would I do that?


Solution

  • Sorry, I would like to correct my Answer above, the issue with the solution above is that if you have more than one feature then this will break the Test.Execution.json file to only generate the results from the last feature that runs and break parallel execution.

    But all is not lost I found a good solution that is even better than the one above, this will make sure the livingDoc is generated after the Test.Execution.json file is made. The code looks like this:

        [Binding]
        [SetUpFixture]
        public static class SetUpFixtureOneTimeTearDown
        {
            [AfterTestRun]
            public static void AfterTestRun()
            {
                AppDomain.CurrentDomain.ProcessExit += (sender, args) =>
                {
                    if (TestEnvironment.Platform.Equals(TestPlatform.Local))
                    {
                        FeatureBase.GenerateLivingDoc();
                    }
                };
            }
        }
    

    This will make sure the LivingDoc is generated at the correct time. Note, that the doc may take a few seconds after the code finishes running for the update to occur.