【问题标题】:How to perform unittest for floating point outputs? - python如何对浮点输出执行单元测试? - Python
【发布时间】:2016-01-16 22:08:23
【问题描述】:

假设我正在为一个返回浮点数的函数编写单元测试,我可以按照我的机器以全精度执行它:

>>> 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) 进行断言,但为了保持固定的小数精度,我仍然需要进行舍入或截断。

但是对于浮点输出的单元测试,还有什么其他方法可以用 Python 处理呢?

【问题讨论】:

    标签: python unit-testing testing floating-point precision


    【解决方案1】:

    float 在 Python 中的精度取决于底层 C 表示。来自Tutorial/Floating Point Arithmetic: Issues and Limitations, 15.1

    今天(2000 年 11 月)几乎所有机器都使用 IEEE-754 浮点 算术,几乎所有平台都将 Python 浮点数映射到 IEEE-754 “双精度”。


    至于测试,一个更好的主意是使用现有的功能,例如TestCase.assertAlmostEqual:

    assertAlmostEqual(first, second, places=7, msg=None, delta=None)

    测试 firstsecond 是否近似(或不近似) 通过计算差异相等,四舍五入到给定的数量 小数(默认为 7),并与零进行比较。如果提供 delta 而不是 placesfirstsecond 之间的差必须小于或等于(或大于)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

    【讨论】:

      【解决方案2】:

      unittest.TestCase 类具有比较浮点数的特定方法:assertAlmostEqualassertNotAlmostEqual。引用文档:

      assertAlmostEqualfirst, second, places=7, msg=None, delta=NoneassertNotAlmostEqualfirst, second, places=7, msg=None, delta=None

      测试 firstsecond 是否近似(或不近似) 通过计算差异相等,四舍五入到给定的数量 小数(默认为 7),并与零进行比较。请注意,这些 方法将值四舍五入到给定的小数位数(即 像round() 函数)而不是有效数字

      如果提供的是 delta 而不是 places 那么两者的区别 firstsecond 必须小于或等于(或大于)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
      

      附带说明,除非您使用pytest 作为测试运行器,否则您应该更喜欢TestCase.assert* 方法而不是裸assert 语句,因为这些方法产生的测试失败消息通常会提供更多信息。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-08
        • 1970-01-01
        • 2019-06-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多