我正在使用NUnit为我的一位同事撰写的图书馆编写单元测试。他的库包含很多Debug.Asserts,它们在无效输入时触发。当我编写单元测试并向其库提供无效输入时,他的Debug.Assert会抛出一个消息框,抱怨输入错误。
我觉得他的库在无效输入上抛出一个断言是件好事,但同时我希望单元测试能够覆盖不良输入。但是当我这样做时,会出现消息框,我必须手动单击“确定”继续进行剩余的单元测试。
如果不清楚,我的问题是单元测试过程在Debug.Assert上停止。人们应该在任何签入之前运行他们的单元测试,它应该是自动的,除非测试失败,否则不应该抛出消息。
在这种情况下,“最佳”方法是什么?
答案 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());
}
测试失败时,不要忘记检查文本输出!