有没有办法在NUnit中进行条件TearDown?
我有一个TestFixture需要为几个测试运行清理代码,我真的不想:
答案 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");
}
}