NUnit - cleanup after test failure

后端 未结 11 950
盖世英雄少女心
盖世英雄少女心 2020-12-24 05:09

We have some NUnit tests that access the database. When one of them fails it can leave database in inconsistent state - which is not an issue, since we rebuild database for

11条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-12-24 06:08

    This idea got me interested, so I did a little digging. NUnit doesn't have this ability out of the box, but there is a whole extensibility framework supplied with NUnit. I found this great article about extending NUnit - it was a good starting point. After playing around with it, I came up with the following solution: a method decorated with a custom CleanupOnError attribute will be called if one of the tests in the fixture failed.

    Here's how the test looks like:

      [TestFixture]
      public class NUnitAddinTest
      {
        [CleanupOnError]
        public static void CleanupOnError()
        {
          Console.WriteLine("There was an error, cleaning up...");
          // perform cleanup logic
        }
    
        [Test]
        public void Test1_this_test_passes()
        {
          Console.WriteLine("Hello from Test1");
        }
    
        [Test]
        public void Test2_this_test_fails()
        {
          throw new Exception("Test2 failed");
        }
    
        [Test]
        public void Test3_this_test_passes()
        {
          Console.WriteLine("Hello from Test3");
        }
      }
    

    where the attribute is simply:

      [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
      public sealed class CleanupOnErrorAttribute : Attribute
      {
      }
    

    And here is how it's executed from the addin:

    public void RunFinished(TestResult result)
    {
      if (result.IsFailure)
      {
        if (_CurrentFixture != null)
        {
          MethodInfo[] methods = Reflect.GetMethodsWithAttribute(_CurrentFixture.FixtureType,
                                                                 CleanupAttributeFullName, false);
          if (methods == null || methods.Length == 0)
          {
            return;
          }
    
          Reflect.InvokeMethod(methods[0], _CurrentFixture);
        }
      }
    }
    

    But here's the tricky part: the addin must be placed in the addins directory next to the NUnit runner. Mine was placed next to the NUnit runner in TestDriven.NET directory:

    C:\Program Files\TestDriven.NET 2.0\NUnit\addins

    (I created the addins directory, it wasn't there)

    EDIT Another thing is that the cleanup method needs to be static!

    I hacked together a simple addin, you can download the source from my SkyDrive. You will have to add references to nunit.framework.dll, nunit.core.dll and nunit.core.interfaces.dll in the appropriate places.

    A few notes: The attribute class can be placed anywhere in your code. I didn't want to place it in the same assembly as the addin itself, because it references two Core NUnit assemblies, so I placed it in a different assembly. Just remember to change the line in the CleanAddin.cs, if you decide to put it anywhere else.

    Hope that helps.

提交回复
热议问题