假设我正在为一个返回浮点数的函数编写一个单元测试,我可以按照我的机器完全精确地执行它:
>>> import unittest
>>> def div(x,y): return x/float(y)
...
>>>
>>> class Testdiv(unittest.TestCase):
... def testdiv(self):
... assert div(1,9) == 0.1111111111111111
...
>>> unittest.main()
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
OS /发行版/机器上相同的完全浮点精度是否相同?
我可以尝试完成这样的单元测试:
>>> class Testdiv(unittest.TestCase):
... def testdiv(self):
... assert round(div(1,9),4) == 0.1111
...
>>>
我也可以使用log(output)
执行断言,但为了保持固定小数精度,我仍然需要进行舍入或截断。
但是,另一种方式应该是pythonically处理浮点输出的单元测试?
答案 0 :(得分:16)
Python中float
的精度取决于底层的C表示。来自Tutorial/Floating Point Arithmetic: Issues and Limitations, 15.1:
今天(2000年11月)几乎所有机器都使用IEEE-754浮点数 算术,几乎所有平台都将Python浮点数映射到IEEE-754 “双精度”。
至于测试,更好的想法是使用现有功能,例如TestCase.assertAmostEqual
:
assertAlmostEqual(first,second,places = 7,msg = None,delta = None)
测试第一个和第二个大约(或不是大约) 等于计算差异,舍入到给定的数量 decimal places (默认为7),并与零进行比较。如果提供 delta 而不是 places ,那么 first 和 second 之间的差异必须小于或等于(或大于) delta 。
示例:
import unittest
def div(x, y): return x / float(y)
class Testdiv(unittest.TestCase):
def testdiv(self):
self.assertAlmostEqual(div(1, 9), 0.1111111111111111)
self.assertAlmostEqual(div(1, 9), 0.1111, places=4)
unittest.main() # OK
如果您更喜欢坚持assert
语句,可以使用math.isclose
(Python 3.5 +):
import unittest, math
def div(x, y): return x / float(y)
class Testdiv(unittest.TestCase):
def testdiv(self):
assert math.isclose(div(1, 9), 0.1111111111111111)
unittest.main() # OK
math.close
的默认相对容差为1e-09,"这可确保两个值在大约9位小数内相同。" 。有关math.close
的更多信息,请参阅PEP 485。
答案 1 :(得分:5)
unittest.TestCase
类具有比较浮点数的特定方法:assertAlmostEqual
和assertNotAlmostEqual
。引用文档:
assertAlmostEqual ( first,second,places = 7,msg = None,delta = None ) assertNotAlmostEqual ( first,second,places = 7,msg = None,delta = None )
测试第一个和第二个大约(或不是大约) 等于计算差异,舍入到给定的数量 decimal places (默认为7),并与零进行比较。请注意这些 方法将值舍入到给定的小数位数(即 比如
round()
函数)而不是有效数字。如果提供了 delta 而不是 places 那么之间的区别 第一个和第二个必须小于或等于(或大于) delta 。
因此,您可以像这样测试函数:
self.assertAlmostEqual(div(1, 9), 0.1111111111111111) # round(a-b, 7) == 0
self.assertAlmostEqual(div(1, 9), 0.1111, 4) # round(a-b, 4) == 0
使用TestCase.assert*
方法优于裸assert
语句,因为后者可以在某些情况下进行优化。此外,这些方法产生的测试失败消息通常提供更多信息。