NUnit与Debug.Assert冲突

时间:2010-02-26 10:29:22

标签: c# nunit assert

我正在使用NUnit为我的一位同事撰写的图书馆编写单元测试。他的库包含很多Debug.Asserts,它们在无效输入时触发。当我编写单元测试并向其库提供无效输入时,他的Debug.Assert会抛出一个消息框,抱怨输入错误。

我觉得他的库在无效输入上抛出一个断言是件好事,但同时我希望单元测试能够覆盖不良输入。但是当我这样做时,会出现消息框,我必须手动单击“确定”继续进行剩余的单元测试。

如果不清楚,我的问题是单元测试过程在Debug.Assert上停止。人们应该在任何签入之前运行他们的单元测试,它应该是自动的,除非测试失败,否则不应该抛出消息。

在这种情况下,“最佳”方法是什么?

3 个答案:

答案 0 :(得分:3)

查看Debug.Assert method的MSDN文档。特别是在“备注”下,它解释了如何禁用UI:

<configuration>
  <system.diagnostics>
    <assert assertuienabled="false" logfilename="c:\\myFile.log" />
  </system.diagnostics>
</configuration>

因此,我建议默认情况下应用程序配置文件具有此功能,并且只要他认为有用,您的同事就会将Assert切换到UI。

答案 1 :(得分:2)

正如Henk已经指出的那样,抑制UI是没用的,因为你希望你的代码失败。如果您不想更改代码,可以编写一个抛出异常的自定义跟踪侦听器,如下所示:

public class ProductionTraceListener : DefaultTraceListener
{
    public override void Fail(string message, string detailMessage)
    {
        string failMessage = message;

        if (detailMessage != null)
        {
            failMessage += " " + detailMessage;
        }

        throw new AssertionFailedException(failMessage);
    }
}

[Serializable]
public class AssertionFailedException : Exception
{
    public AssertionFailedException() { }
    public AssertionFailedException(string message) : base(message) { }
    public AssertionFailedException(string message, Exception inner) 
        : base(message, inner) { }
    protected AssertionFailedException(SerializationInfo info,
        StreamingContext context) : base(info, context) { }
}

您可以按如下方式注册:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.diagnostics>
    <trace>
      <listeners>
        <clear />
        <add name="Default"
          type="[Namespace].ProductionTraceListener, [Assembly]" />
      </listeners>
    </trace>
  </system.diagnostics>
</configuration>

正如您可能对跟踪侦听器的名称ProductionTraceListener所期望的那样,我在生产环境(Web应用程序)中使用该东西,而不是在我的单元测试中。虽然您可以在单元测试中使用此技巧,但我建议您更改代码。 IMO你应该只对那些永远不会运行的代码路径使用断言,如果它们这样做,测试应该失败。在你的情况下,你想在断言失败时进行一次成功的测试,这是违反直觉的。

我的建议是更改代码并使用正常的if (x) throw ArgumentException()检查前置条件(或使用CuttingEdge.Conditions)并将这些断言仅用于永远不应运行的代码路径。另请尝试使用Trace.Assert而不是Debug.Assert,因为您还希望在生产环境中检查这些断言。完成后,您可以在生产环境中使用ProductionTraceListener,并在单元测试中使用此UnitTestTraceListener

public class UnitTestTraceListener : DefaultTraceListener
{
    public override void Fail(string message, string detailMessage)
    {
        string failMessage = message;

        if (detailMessage != null)
        {
            failMessage += " " + detailMessage;
        }

        // Call to Assert method of used unit testing framework.
        Microsoft.VisualStudio.TestTools.UnitTesting.Assert.Fail(
            failMessage);
    }
}
祝你好运。

答案 2 :(得分:2)

我觉得有效的一个简单选项是使用标准ConsoleTraceListener,这将允许Debug.Assert检查触发,但会将其输出定向到NUnit Text Output选项卡,而不会影响单元测试。< / p>

您可以将其添加到测试设置中......

[SetUp]
public void SetUp()
{
    // Replace pop-up assert trace listener with one that simply logs a message.
    Debug.Listeners.Clear();
    Debug.Listeners.Add(new ConsoleTraceListener());
}

测试失败时,不要忘记检查文本输出!