开发者

Debug.Assert interferes with MSTests, how do I work around it?

开发者 https://www.devze.com 2022-12-19 02:26 出处:网络
So I have a method i\'m unit testing via MSTests to ensure it throws an exception properly on bad data coming in.

So I have a method i'm unit testing via MSTests to ensure it throws an exception properly on bad data coming in.

However that method has Debug.Assert so it's caught while debugging if it happens during an actual test where I'm in debug mode trying to find a bug.

So the unit tests fail at being automatable when run in this way because the Assert statement comes up with Abort, Retry, Ignore. All 3 situations are important:

I'm debugging and looking for a problem, so I want the Debug.Assert to be available. The code should have the proper guard clause so if it happens i开发者_StackOverflown production an exception is thrown. My unit test should be completely automated and run without manual clicking.

What's the work around?


So far when the unit tests are run locally Nicole's solution didn't do what I wanted, because I was intentionally passing in values that would trip the Asserts to make sure exceptions are thrown, interferes with running the unit tests automated locally. I suppose it would work if I was willing to accept the [Conditional("DEBUG")] compilation attribute and run the unit tests in release mode. If I want that behavior I can provide a test level(or assembly level) wrapper with the [Conditional("DEBUG")] in the testing assembly, but this one I can utilize from a pre-compiled reusable class library.

This gets pretty close to what I want, with the additional requirement of calling Trace.Listeners.Clear(); in my test suite.

/// <summary>
/// To suppress UI assert messages use:
/// Trace.Listeners.Clear();
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="assertAgainst"></param>
/// <param name="condition"></param>
/// <param name="exception"></param>
/// <returns></returns>
public static T Assert<T>(this T assertAgainst, Func<T,bool> condition,Func<Exception> exception)
{
    var conditionMet = condition(assertAgainst);
    if (Debugger.IsAttached)
        Debug.Assert(conditionMet);

        //assertAgainst.Assert(x => x != null, () => new NullReferenceException());
        if (!conditionMet)
            throw exception();

    return assertAgainst;
}


Instead of calling Debug.Assert directly, you could call a wrapper method that checks whether a debugger is attached before invoking Debug.Assert. (Obviously, it should throw an exception if there is no debugger attached.) e.g.:

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


I just came across the same issue but then I realized that this scenario shouldn't ever come up unless there is an error in your code. In which case I wouldn't really mind the assert popping up. Here is my chain of reasoning:

  1. A Debug.Assert should only be hit when a function's preconditions are not met (or if there is an error in the function it self).
  2. A unit test should check a function's post condition.
  3. A function only needs to produce its post conditions if all of its preconditions are met so there is no point in writing a unit test for a function that passes it invalid preconditions.


This assert won't interfere with automated tests, it will fail the test case if the assert fails, but execution will continue.

0

精彩评论

暂无评论...
验证码 换一张
取 消