34

I've got functions, which sometimes return NaNs with float('nan') (I'm not using numpy).

How do I write a test for it, since

assertEqual(nan_value, float('nan'))

is just like float('nan') == float('nan') always false. Is there maybe something like assertIsNan? I could not find anything about it…

tamasgal
  • 24,826
  • 18
  • 96
  • 135
  • possible duplicate of [How do you test to see if a double is equal to NaN in Java?](http://stackoverflow.com/questions/1456566/how-do-you-test-to-see-if-a-double-is-equal-to-nan-in-java) – Raedwald Jun 28 '14 at 07:38
  • 1
    It cannot be a possible duplicate if the language is different. – Mike Williamson Sep 24 '20 at 17:09

4 Answers4

37

I came up with

assertTrue(math.isnan(nan_value))
tamasgal
  • 24,826
  • 18
  • 96
  • 135
13

math.isnan(x) will raise a TypeError if x is neither a float nor a Real.

It's better to use something like this :

import math


class NumericAssertions:
    """
    This class is following the UnitTest naming conventions.
    It is meant to be used along with unittest.TestCase like so :
    class MyTest(unittest.TestCase, NumericAssertions):
        ...
    It needs python >= 2.6
    """

    def assertIsNaN(self, value, msg=None):
        """
        Fail if provided value is not NaN
        """
        standardMsg = "%s is not NaN" % str(value)
        try:
            if not math.isnan(value):
                self.fail(self._formatMessage(msg, standardMsg))
        except:
            self.fail(self._formatMessage(msg, standardMsg))

    def assertIsNotNaN(self, value, msg=None):
        """
        Fail if provided value is NaN
        """
        standardMsg = "Provided value is NaN"
        try:
            if math.isnan(value):
                self.fail(self._formatMessage(msg, standardMsg))
        except:
            pass

You can then use self.assertIsNaN() and self.assertIsNotNaN().

LaGoutte
  • 418
  • 4
  • 13
  • 2
    Nice. You can achieve the same without importing the math module by simply using the comparison `value != value` which evaluates to True for nan values. – Richard Jan 24 '20 at 18:03
  • 1
    @Richard That is very dangerous and not at all to the point of the question. Context: `float("NaN") != float("NaN")` would evaluate to `True`, but so would `float("NaN") != 3`, which is not at all what the user is trying to do (assert if the value _is_ nan). – Slobodan Ilic Mar 18 '21 at 11:47
  • 1
    @SlobodanIlic I think you misunderstood my comment. Provided you have the variable `a = 3`, then you would not write `float('nan') != a` to check if its value is nan. You would write `is_nan = (a != a)`. That way `is_nan` is only True, if a is indeed nan. – Richard Mar 18 '21 at 18:02
  • 1
    @Richard You are correct, I did misunderstand. Thanks for clarifying. I'm gonna leave the original comment in place for consistency. – Slobodan Ilic May 17 '22 at 11:35
4

Update with NumPy: I know the OP is not using numpy. However, I had to use numpy and didn't find any post. So I'll leave the answer here for anybody that may need help. It also works perfectly with unittest library.

import numpy as np
np.testing.assert_equal(nan_value, np.nan)
user3503711
  • 1,623
  • 1
  • 21
  • 32
1

Keying off of @user3503711's answer, the following worked for me:

numpy.isnan(nan_value)

I am using numpy==1.22.2. See https://numpy.org/doc/1.22/reference/generated/numpy.isnan.html

dirtyqwerty
  • 185
  • 2
  • 16