单元测试 - 如何断言两个可能为 NaN 的值相等

8

在我的测试用例中,我假设如果两个值都是NaN,那么它们相等。使用unittest断言表达这一点的方法是什么?下面介绍的两个常见函数都不能处理这种情况。

v1 = np.nan
v2 = np.nan
self.assertEquals(v1, v2)
self.assertTrue(v1 == v2)

目前对我有效的解决方案是在 assertTrue 中使用布尔表达式:

self.assertTrue(v1 == v2 or (np.isnan(v1) and np.isnan(v2))

我可能会编写自己的断言方法,例如 assertBothNan,或者如果您始终希望具有该行为,则覆盖 assertEquals。至于如何检查值是否为 NaN,请参考:https://dev59.com/KWQn5IYBdhLWcg3wXGKr - jonrsharpe
这样不行,v1==v2 会返回 False。你应该分别检查两个值是否为 NaN,然后编写自己的断言方法。 - toti08
1
这就是为什么我正在寻找一个解决方案,涵盖了两个值都不是NaN和它们都是NaN的情况。如果目前只有一个复杂的布尔表达式可用,我也能理解。 - Krzysztof Słowiński
5个回答

14

您可以使用:

numpy.testing.assert_equal(v1, v2)

文档中:

此函数将NaN比较处理为如果NaN是“正常”数字。也就是说,如果两个对象在相同的位置具有NaN,则不会引发任何断言。这与IEEE标准上的NaN相反,该标准规定,与任何东西进行比较时,NaN必须返回False。

当值不相等时,它会抛出AssertionError,并且应该与pytest一起正常工作,但它可能不适合unittest测试。

另一个选择是:

numpy.isclose(v1, v2, equal_nan=True)

但显然它是用来替代math.isclose,而不是==


请注意,此方法不适用于“object”数据类型:例如np.array(["hello",np.nan],dtype='object')会引发错误。 - Fee

5

检查两个NaN是否相等是没有意义的。最好的做法是以不同的方式进行检查,例如:

check = numpy.isnan(v1) and numpy.isnan(v2)
self.assertTrue(check)

2
你可以使用math.isnan
self.assertTrue(math.isnan(v1) and math.isnan(v2))

1
你可以分别检查它们是否为 NaN。为此,我建议使用以下类:
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

这很简单:

v1 = np.nan
v2 = np.nan
self.assertIsNaN(v1)
self.assertIsNaN(v2)

1
一种检查NaN的标准方法是:

使用nan进行检查

assert (v1 != v1) and (v2 != v2)

即不等于自身的东西,例如:

>>> n = float('nan')
>>> n != n
True

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接