NUnit有条件拆解?

时间:2009-07-29 12:26:00

标签: unit-testing nunit

有没有办法在NUnit中进行条件TearDown?

我有一个TestFixture需要为几个测试运行清理代码,我真的不想:

  1. 在每次测试中运行TearDown方法
  2. 创建一个私有帮助器方法,并从需要清理的测试中调用它,如果我可以避免它

3 个答案:

答案 0 :(得分:2)

不幸的是。

你不能在[TestFixtureTearDown]中进行清理,所以一旦所有的测试都完成了吗?我想这取决于清理是否在下一次测试运行之前完成。

或者,将那些需要在另一个类/ TextFixture中进行清理的测试放在一起,远离其他测试。然后你可以在那里使用一个不需要条件的TearDown。

修改 我刚才想到的一件事,可以实现目标,虽然可能实际上并不值得为此特殊需求,但是你可以扩展NUnit - 创建你自己的自定义属性,你可以随意处理。这是here。就像我说的那样,我认为你不应该为此做出这样的路线,但是知道这一点非常有用

答案 1 :(得分:0)

您可以将主TearDown放在基类中:

[TearDown]
public virtual void TearDown()
{
  // Tear down things here
}

然后在你没有运行拆卸代码的测试的类中覆盖它:

[TearDown]
public override void TearDown()
{
  // By not calling base.TearDown() here you avoid tearing down
}

答案 2 :(得分:0)

使用 BaseTest 中的测试扩展所有类

    public class BaseTest
    {
        [SetUp]
        public void BeforeTest()
        {
            GetService<NUnitHooksController>().ExecuteBeforeTestHooks(this);
        }

        [TearDown]
        public void AfterTest()
        {
            GetService<NUnitHooksController>().ExecuteAfterTestHooks(this);
        }
    }

使用 AfterTest 和 BeforeTest 钩子。有类别和无类别均可使用。

    public class ExampleTest : BaseTest
    {
        [Test, Category("asdasd")]
        public void Test01()
        {
           ...
        }

        [AfterTest("asdasd")]
        public void ExampleHook()
        {
           ...
        }

    }
    public class NUnitHooksController
    {
        private readonly ILogger _log;

        public NUnitHooksController(ILogger log)
        {
            _log = log;
        }

        public void ExecuteBeforeTestHooks(object testClass)
        {
            ExecuteHooks(testClass, typeof(BeforeTestAttribute));
        }

        public void ExecuteAfterTestHooks(object testClass)
        {
            ExecuteHooks(testClass, typeof(AfterTestAttribute));
        }

        private MethodInfo[] GetHookMethods(object currentTestClass, Type attributeType)
        {
            return currentTestClass
                .GetType()
                .GetMethods()
                .Where(m => m.GetCustomAttributes(attributeType, false).Length > 0)
                .ToArray();
        }

        private void ExecuteHooks(object testClass, Type requiredAttributeType)
        {
            var hooks = GetHookMethods(testClass, requiredAttributeType);
            var testCategories = GetTestCategories();

            foreach (var hook in hooks)
            {
                var allAttributes = hook.GetCustomAttributes(requiredAttributeType, true);
                foreach (var attribute in allAttributes)
                {
                    if (!attribute.GetType().IsEquivalentTo(requiredAttributeType))
                    {
                        continue;
                    }

                    var hookCategories = GetCategoriesFromAttribute(attribute);

                    // if we do not have specific category on hook
                    // or we have at least one same category on hook and test
                    if (!hookCategories.Any() || hookCategories.Intersect(testCategories).Any())
                    {
                        ExecuteHookMethod(testClass, hook);
                    }
                }
            }
        }

        private object[] GetTestCategories()
        {
            return TestContext.CurrentContext.Test.Properties["Category"].ToArray();
        }

        private void ExecuteHookMethod(object testClass, MethodInfo method)
        {
            var hookName = method.Name;
            _log.Information($"Executing - '{hookName}' hook");

            try
            {
                method.Invoke(testClass, Array.Empty<object>());
            }
            catch (Exception e)
            {
                _log.Error($"Executing of - '{hookName}' hook failed - {e}");
            }
        }

        private string[] GetCategoriesFromAttribute(object attribute)
        {
            if (attribute is BeforeTestAttribute beforeTestAttribute)
            {
                return beforeTestAttribute.Categories;
            }

            if (attribute is AfterTestAttribute afterTestAttribute)
            {
                return afterTestAttribute.Categories;
            }

            throw new ArgumentException($"{attribute.GetType().FullName} - does not have categories");
        }
    }