【问题标题】:Why does Assert.AreEqual(1.0, double.NaN, 1.0) pass?为什么 Assert.AreEqual(1.0, double.NaN, 1.0) 通过?
【发布时间】:2010-12-19 07:07:08
【问题描述】:

简短的问题,为什么Assert.AreEqual(1.0, double.NaN, 1.0) 通过?而Assert.AreEqual(1.0, double.NaN) 失败。

这是 MSTest (Microsoft.VisualStudio.QualityTools.UnitTestFramework) 中的错误还是我在这里遗漏了什么?

最好的问候,埃吉尔。


更新:应该补充一下,我的问题背后的原因是,由于某些线性代数矩阵运算的结果是 NaN 或 (+/-)Infinity,我有一堆单元测试不幸通过了。单元测试很好,但是由于当实际或/和预期为 NaN 或 Infinity 时,带有 delta 的双精度的 Assert.AreEqual 将通过,所以我只能相信我正在测试的代码是正确的。

【问题讨论】:

标签: .net mstest double assert nan


【解决方案1】:

小心。 NaN 很奇怪,有点像许多 DBMS 中的 null,您不应该将值与它进行比较(直接或使用 Assert.AreEqual)。来自Double.NaN 的文档:

使用 IsNaN 判断一个值是否 不是一个数字。这是不可能的 判断一个值是否不是 通过将其与另一个进行比较来获得数字 值等于 NaN。

double zero = 0;
Console.WriteLine((0 / zero) == Double.NaN);  // prints false
Console.WriteLine(Double.IsNaN(0 / zero));  // prints true

您必须查看 Assert(double, double, double) 的内部以了解发生了什么,但通常,您依赖于相对于 NaN 的未定义行为。

【讨论】:

  • 我的问题背后的故事是一堆单元测试,不幸的是,由于某些线性代数矩阵运算的结果是 NaN/(+/-)Infinity,这些单元测试通过了。单元测试很好,但是由于当实际或/和预期为 NaN 或 Infinity 时,带有 delta 的双精度数上的 Assert.AreEqual 将通过,所以我不得不相信我的代码确实有效......
  • 我明白了。从表面上看,这种行为是不正确的,您有理由在 Microsoft Connect 上提出问题。如果你愿意,可以连接一个符号服务器,看看 Assert.AreEqual(double, double) 与 Assert.AreEqual(double, double, double) 有何不同。
【解决方案2】:

答案已过时。如果错误已被修复,何时以及在哪个程序集的哪个版本中?

没错,它已在 VS2013 中使用 Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll 程序集版本 10.0.0.0 修复。存在于旧版 GAC 中,c:\windows\assembly,它也有 10.1.0.0 版本。

这里有一个 DLL Hell 故事,10.1.0.0 版本是 VS2010 中使用的版本。它有错误,没有正确检查 Double.NaN。微软犯了一个错误,他们修复了 10.1.0.0 但没有更改版本号。所以在安装 VS2013 之后安装 VS2010 的任何人都会受到伤害,它会用有缺陷的版本覆盖 DLL。

解开 DLL Hell 从未如此简单,但从connect article 以及它在我的机器上的运行方式可以看出,他们从客户的投诉中识别出故障模式。并提供了一个修复,在更新中交付。不清楚哪个,在 2014 年 7 月之后。您现在将使用 v10.0.0.0,MSTest.exe 测试运行程序和 QTAgents 有一个带有 <bindingRedirect> 的 .config 文件,该文件从 10.1.0.0 重定向到 10.0.0.0(不是一个错字)。请务必获取最新的更新,目前 4. 如果您不确定自己安装了哪些更新,请查看帮助 + 关于。

作为记录,固定代码获得了对 Double.NaN 的特定检查,如下所示:

public static void AreEqual(double expected, double actual, double delta, string message, params object[] parameters)
{
    if ((double.IsNaN(expected) || double.IsNaN(actual)) || double.IsNaN(delta))
    {
        string str = (string) FrameworkMessages.AreEqualDeltaFailMsg((message == null) ? string.Empty : ReplaceNulls(message), expected.ToString(CultureInfo.CurrentCulture.NumberFormat), actual.ToString(CultureInfo.CurrentCulture.NumberFormat), delta.ToString(CultureInfo.CurrentCulture.NumberFormat));
        HandleFail("Assert.AreEqual", str, parameters);
    }
    if (Math.Abs((double) (expected - actual)) > delta)
    {
        string str2 = (string) FrameworkMessages.AreEqualDeltaFailMsg((message == null) ? string.Empty : ReplaceNulls(message), expected.ToString(CultureInfo.CurrentCulture.NumberFormat), actual.ToString(CultureInfo.CurrentCulture.NumberFormat), delta.ToString(CultureInfo.CurrentCulture.NumberFormat));
        HandleFail("Assert.AreEqual", str2, parameters);
    }
}

【讨论】:

  • 谢谢汉斯,一如既往的彻底。 “dll 地狱”解释了在我同事的机器之间重现此错误时的不一致。
  • 似乎即使在“修复”之后,Assert.AreEqual(double.NaN, double.NaN, 0.001); 也会失败。我想在下一个补丁发布之前,我必须编写自己的双重断言。
【解决方案3】:

MSTest 对Assert.AreEqual<double>(expected, actual, delta) 方法使用以下公式:

if (Math.Abs(expected - actual) > delta)
    Assert.HandleFail("Assert.AreEqual", ...)

操作减少到double.NaN > delta,在这种情况下返回true。或未定义。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-02
    • 2019-09-28
    • 2011-01-31
    • 1970-01-01
    • 1970-01-01
    • 2012-02-07
    • 1970-01-01
    相关资源
    最近更新 更多