tags:

views:

145

answers:

3

Why am I getting this result?

[TestMethod]
public void nan_test()
{
    Assert.AreEqual(1, double.NaN, 1E-1); <-- Passes
    Assert.AreEqual(1, double.NaN);       <-- Fails
}

What difference does the delta have in asserting NaN equals a number? Surely it should always return false. I am aware of IsNaN, but that's not useful here (see below).

Background: I have a function returning NaN (erroneously) , it was meant to be a real number but the test still passed. I'm using the delta because it's double precision equality, the original test used 1E-9.

+1  A: 

Could you use this test for NaN instead?

double.IsNaN(somenNumber)
Jake Pearson
Yea but I don't want my result to be NaN, if I just ran the test without debugging with an expected value, it would pass. Not good.
RichK
+1  A: 

Have a look here: http://stackoverflow.com/questions/1780004/why-do-mstests-assert-areequal1-0-double-nan-0-0-pass

Edit:

there is definitely a bug in Assert.AreEqual. in VS 2008's Microsoft.VisualStudio.QualityTools.UnitTestFramework it's coded as

if (Math.Abs((double) (expected - actual)) > delta)
{
    // report error
}

As in your case Math.Abs((double) (expected - actual)) is a double.NaN, the comparison yields false :-)

Vlad
Excellent, thanks. The OP of that question seems to have got the problem doing exactly the same thing as me, weird.
RichK
+1  A: 

When you use Assert.AreEqual(1, double.NaN), it tries an equality test on the numbers and of course it fails, since double.NaN isn't equal to anything.

When you do Assert.AreEqual(1, double.NaN, 1E-1), it has to do arithmetic on the numbers. Specifically, it computes

Math.Abs((double) (expected - actual)) > delta
Math.Abs(1 - double.NaN) > 1E-1
Math.Abs(double.NaN) > 1E-1 // All arithmetic with double.NaN returns double.NaN
double.NaN > 1E-1 // All comparisons with double.NaN return false (except !=)

which is false. It looks like the actual delta isn't larger than the delta you passed, but only since it is trying to indicate that you cannot perform the comparison.

Moral of the story: the behavior of NaN is pretty crazy (but the best some smart people could come up with). Do your best to check for NaN before performing any computations where you cannot have the error propagate up silently, like this one.

Mike Graham
Good explanation, thanks
RichK