NUnit 3 扩展失败测试失败 Debug.Assert

NUnit 3 Extension to Fail Test on a Failed Debug.Assert

我正在尝试编写一个 NUnit 3 (3.8.1) 扩展,让测试在失败时失败 Debug.Assert(...)(而不是默默地 运行 通过甚至挂起,因为它显示失败的断言对话框)。

在 NUnit 2 插件中,我能够通过取消注册所有调试跟踪侦听器并添加我自己的只抛出异常的侦听器来做到这一点(如 here 所解释的示例)。但是,这似乎不再适用于 NUnit 3。

我能够成功部署扩展程序并且它的代码正在执行。

[Extension(Description = "Failed Assertions Tracker", EngineVersion = "3.4")]
public class TrackerEventListener : ITestEventListener
{
    public void OnTestEvent(string report)
    {
        Console.WriteLine(report); // prints -> so I know this method is being called
        Debug.Listeners.Clear();
        Debug.Listeners.Add(new UnitTestTraceListener());
    }
}

但是,不幸的是,我的单元测试显示仍然安装了 DefaultTraceListener

[Test]
public void FailingAssertionShouldNotHang()
{
    foreach (object listener in Debug.Listeners)
    {
        Console.WriteLine(listener.GetType().FullName);
    }
    Debug.Fail("I'm sorry. I've failed.");
}

因此测试显示对话框而不是简单地失败。

我做错了什么?我怀疑调用静态 Listeners 集合是无效的,因为实际测试是 运行 在不同的上下文中(不同的 AppDomain,进程,?)。但是如果是这样,我该如何解决呢?

请务必记住,NUnit 3 扩展虽然在少数情况下能够替代 NUnit 2 插件,但实际上是完全不同的技术。 NUnit 3 Extensions 扩展了与框架分离的引擎。

在这种情况下,您的扩展正在设置跟踪侦听器,它将捕获引擎生成的任何调试跟踪或断言输出。如果引擎包含 Trace 语句(它不包含),您将获得输出。与此同时,该框架正在愉快地继续 运行 自行测试。

任何成功捕获 Trace 的代码都必须是测试的实际框架执行的一部分。这给了你两个选择。

  1. 创建将捕获跟踪的自定义属性。自定义属性允许您在创建或执行测试时采取行动。它们是通过实现框架支持的各种接口创建的。在您的情况下,您可能希望在程序集级别提供属性,以便捕获程序集产生的 all 输出。

  2. 创建代码作为测试的一部分,根本不扩展框架。您可能希望使用 OneTimeSetUp 属性在程序集级别 SetUpFixture 中捕获 Trace 输出,并在 OneTimeTearDown 属性下释放它。由于这种方法比创建自定义属性更简单,因此我会使用它。