开发者

Why does Assert.AreEqual(1.0, double.NaN, 1.0) pass?

开发者 https://www.devze.com 2022-12-11 23:51 出处:网络
Short question, why does Assert.AreEqual(1.0, double.NaN, 1.0) pass? Whereas Assert.AreEqual(1.0, double.NaN) fails.

Short question, why does Assert.AreEqual(1.0, double.NaN, 1.0) pass? Whereas Assert.AreEqual(1.0, double.NaN) fails.

Is it a bug in MSTest (Microsoft.VisualStudio.QualityTools.UnitTestFramework) or am I missing something here?

Best regards, Egil.


Update: Should probably add, that the reason behind my question is, that I have a bunch of unit tests that unfortunately passed due to the result of some linear algebraic matrix operation being NaN or (+/-)Infinity.开发者_运维百科 The unit tests are fine, but since Assert.AreEqual on doubles with a delta will pass when actual or/and expected are NaN or Infinity, I was left to believe that the code I was testing was correct.


Be careful. NaN is weird, somewhat like null in many DBMSs, and you shouldn't be comparing values to it (either directly, or with Assert.AreEqual). From the docs for Double.NaN:

Use IsNaN to determine whether a value is not a number. It is not possible to determine whether a value is not a number by comparing it to another value equal to NaN.

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

You'd have to peer at the internals of Assert(double, double, double) to see what's going on, but in general, you're depending on undefined behavior relative to NaN.


The answers are out-of-date. If the bug has been fixed, when, and in which versions of what assembly?

That's correct, it was fixed in VS2013 with the Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll assembly, version 10.0.0.0. Present in the legacy GAC, c:\windows\assembly, it also has the 10.1.0.0 version.

There is a DLL Hell story here, the 10.1.0.0 version was the one used in VS2010. It had the bug, not properly checking for Double.NaN. Microsoft made a mistake, they fixed 10.1.0.0 but did not change the version number. So anybody that installed VS2010 after installing VS2013 is going to get hurt, it is going to overwrite the DLL with the buggy version.

Unraveling DLL Hell is never that simple, but it appears from the connect article and from the way it works on my machine that they identified the failure mode from the customer's complaint. And provided a fix, delivered in an update. Not clear which, after July 2014. You'll now use v10.0.0.0, the MSTest.exe test runner and the QTAgents have a .config file with a <bindingRedirect> that redirects from 10.1.0.0 to 10.0.0.0 (not a typo). Be sure to obtain the latest update, currently 4. Look in Help + About if you are not sure what update you have installed.

For the record, the fixed code acquired specific checks for Double.NaN, it looks like this:

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


MSTest uses the following formula for the Assert.AreEqual<double>(expected, actual, delta) method:

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

The operation reduces to double.NaN > delta, which returns true in this case. Or undefined.

0

精彩评论

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

关注公众号