Debug.Assert 会干扰 MSTests,我该如何解决它?

发布于 2024-08-19 20:21:21 字数 327 浏览 3 评论 0原文

所以我有一个方法,我通过 MSTests 进行单元测试,以确保它在传入错误数据时正确抛出异常。

但是该方法具有 Debug.Assert,因此如果它发生在我处于调试状态的实际测试期间,它会在调试时被捕获模式试图找到错误。

因此,以这种方式运行时,单元测试无法自动化,因为 Assert 语句出现了 Abort、Retry、Ignore。所有 3 种情况都很重要:

我正在调试并寻找问题,因此我希望 Debug.Assert 可用。 代码应该具有适当的保护子句,因此如果在生产中发生这种情况,则会引发异常。 我的单元测试应该完全自动化,无需手动点击即可运行。

有什么解决办法吗?

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 in production an exception is thrown.
My unit test should be completely automated and run without manual clicking.

What's the work around?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

安人多梦 2024-08-26 20:21:21

到目前为止,当单元测试在本地运行时,Nicole 的解决方案并没有达到我想要的效果,因为我故意传递的值会触发断言以确保抛出异常,从而干扰在本地自动运行单元测试。我想如果我愿意接受 [Conditional("DEBUG")] 编译属性并在发布模式下运行单元测试,它就会起作用。如果我想要这种行为,我可以在测试程序集中提供一个带有 [Conditional("DEBUG")] 的测试级别(或程序集级别)包装器,但是我可以从预编译中使用这个包装器可重用的类库。

这非常接近我想要的,但还需要调用 Trace.Listeners.Clear();在我的测试套件中。

/// <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;
}

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;
}
小帐篷 2024-08-26 20:21:21

您可以调用一个包装器方法,在调用 Debug.Assert 之前检查是否附加了调试器,而不是直接调用 Debug.Assert。 (显然,如果没有附加调试器,它应该抛出异常。)例如:

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

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();
    }
}
自演自醉 2024-08-26 20:21:21

我刚刚遇到了同样的问题,但后来我意识到除非代码中有错误,否则这种情况不应该出现。在这种情况下,我真的不介意断言的弹出。这是我的推理链:

  1. 只有在不满足函数的先决条件(或者函数本身存在错误)时,才应命中 Debug.Assert。
  2. 单元测试应该检查函数的后置条件。
  3. 如果函数的所有前置条件都满足,则只需生成其后置条件,因此为传递无效前置条件的函数编写单元测试是没有意义的。

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.
白首有我共你 2024-08-26 20:21:21

此断言 不会干扰自动化测试,如果断言失败,测试用例将会失败,但执行将继续。

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文