在我的测试用例中,我假设如果两个值是
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))
您可以使用:
numpy.testing.assert_equal(v1, v2)
来自文档:
此函数处理 NaN 比较,就好像 NaN 是“正常”数字一样。 也就是说,如果两个对象在同一个对象中都具有 NaN,则不会引发断言 职位。这与 NaN 的 IEEE 标准形成鲜明对比,该标准 表示 NaN 与任何内容相比都必须返回 False。
当值不相等时,它会抛出 AssertionError ,并且它应该可以与 pytest 一起正常工作,但它可能不太适合单元测试测试。
另一种选择是:
numpy.isclose(v1, v2, equal_nan=True)
但显然它是
math.isclose
的替代品,而不是 ==
。
检查两个 NaN 是否相等是没有意义的。您能做的最好的事情就是以不同的方式检查它,例如:
check = numpy.isnan(v1) and numpy.isnan(v2)
self.assertTrue(check)
您可以使用math.isnan
self.assertTrue(math.isnan(v1) and math.isnan(v2))
您可以分别检查它们是否为 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)
检查
nan
s 的标准方法是
assert (v1 != v1) and (v2 != v2)
即不等于自身的东西,例如:
>>> n = float('nan')
>>> n != n
True
为了比较可能包含 NaN 值的 Python 数据结构(例如与assertListEqual/assertDictEqual),可以使用以下表达式代替 NaN 常量:
pytest.approx(np.nan, nan_ok=True)