我能否配置NUnit,使得在运行测试时Debug.Fail不会显示消息框?

10

我有这个属性:

    public SubjectStatus Status
    {
        get { return status; }
        set
        {
            if (Enum.IsDefined(typeof(SubjectStatus), value))
            {
                status = value;
            }
            else
            {
                Debug.Fail("Error setting Subject.Status", "There is no SubjectStatus enum constant defined for that value.");
                return;
            }
        }
    }

还有这个单元测试

    [Test]
    public void StatusProperty_StatusAssignedValueWithoutEnumDefinition_StatusUnchanged()
    {
        Subject subject = new TestSubjectImp("1");

        //  assigned by casting from an int to a defined value
        subject.Status = (SubjectStatus)2;
        Assert.AreEqual(SubjectStatus.Completed, subject.Status);            

        //  assigned by casting from an int to an undefined value
        subject.Status = (SubjectStatus)100;
        //  no change to previous value
        Assert.AreEqual(SubjectStatus.Completed, subject.Status);            
    }

我是否可以在运行测试时防止Debug.Fail显示消息框,但允许在调试应用程序时显示一个消息框?


我已经更新了我的答案,包含了NUnit的跟踪侦听器插件实现,如果您感兴趣的话。 - Mark Simpson
太好了,这正是我正在寻找的信息! - Grokodile
3个回答

10

一种不需要更改生产代码或编写自定义NUnit插件的替代方法是在设置夹具中替换跟踪侦听器。

例如,在您的测试所在的命名空间中添加以下类:

using System;
using System.Diagnostics;
using NUnit.Framework;

[SetUpFixture]
public class NUnitSetup
{
    // Field to hold exisitng trace listeners so they can be restored after test are run.
    private TraceListener[] originalListeners = null;

    // A trace listener to use during testing.
    private TraceListener nunitListener = new NUnitListener();

    [SetUp]
    public void SetUp()
    {
        // Replace existing listeners with listener for testing.
        this.originalListeners = new TraceListener[Trace.Listeners.Count];
        Trace.Listeners.CopyTo(this.originalListeners, 0);
        Trace.Listeners.Clear();
        Trace.Listeners.Add(this.nunitListener);
    }

    [TearDown]
    public void TearDown()
    {
        // Restore original trace listeners.
        Trace.Listeners.Remove(this.nunitListener);
        Trace.Listeners.AddRange(this.originalListeners);
    }

    public class NUnitListener : DefaultTraceListener
    {
        public override void Fail(string message)
        {
            Console.WriteLine("Ignoring Debug.Fail(\"{0}\")", message);
        }

        public override void Fail(string message, string detailMessage)
        {
            Console.WriteLine("Ignoring Debug.Fail(\"{0},{1}\")", message, detailMessage);
        }
    }
}

1
你甚至不需要自定义跟踪侦听器,只需安装ConsoleTraceListener即可。然后,所有的Debug.Assert/Fail消息都会发送到NUnit文本输出选项卡,而不会影响测试。 - yoyo
NUnit 3.0 更新: [SetupFixture] 与 [SetUp] 和 [TearDown] 冲突。但没关系 - 只需将整个类(初始 [SetUpFixture] 不用)插入 TextFixture 中即可。更好的方法是,将 [SetUp] 更改为 [OneTimeSetUp] (TearDown 同理),这样它只会进行一次替换!这个方法非常有效! - shipr

2
我一直以来的标准做法是创建一个NUnit插件。该插件简单地取消注册默认跟踪侦听器并注册一个替代品,当触发Assert/Trace.Fail时会抛出异常。我喜欢这种方法,因为如果断言失败,测试仍将失败,你不会看到任何弹出消息框,并且不必修改生产代码。
编辑--以下是完整的插件代码。但是,构建实际插件需要自己完成--请查看NUnit网站 :)
[NUnitAddin]
public class NUnitAssertionHandler : IAddin
{
    public bool Install(IExtensionHost host)
    {
        Debug.Listeners.Clear();
        Debug.Listeners.Add(new AssertFailTraceListener());
        return true;
    }

    private class AssertFailTraceListener : DefaultTraceListener
    {
        public override void Fail(string message, string detailMessage)
        {
            Assert.Fail("Assertion failure: " + message);
        }

        public override void Fail(string message)
        {
            Assert.Fail("Assertion failure: " + message);
        }
    }
}

还好,有一些需要做的事情,包括将文件设置为复制本地=false和其他一些小问题,但是我现在没有项目在我面前,所以无法发布确切的步骤。它只是一个插件.dll,其中只有一个类 :) - Mark Simpson

0

不要直接调用 Debug.Assert,而是可以调用一个包装方法,在调用 Debug.Assert 之前检查是否已经连接了调试器。(假设如果没有连接调试器,则应该抛出异常,以便测试失败。)例如:

[Conditional("DEBUG")] 
public static void Assert(bool condition) 
{ 
    if (Debugger.IsAttached) 
    { 
        Debug.Assert(condition); 
    } 
    else 
    { 
        throw new SomeException(); 
    } 
}

谢谢,我会写一个包装类,这样我就可以随时切换了,好主意。 - Grokodile

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接