224

如何assert almost equal使用 py.test 进行浮动而不诉诸于:

assert x - 0.00001 <= y <= x + 0.00001

更具体地说,了解一个快速比较浮点对的简洁解决方案将很有用,而无需解包它们:

assert (1.32, 2.4) == i_return_tuple_of_two_floats()
4

8 回答 8

368

我注意到这个问题专门询问了 py.test。py.test 3.0 包含一个approx()对此目的非常有用的函数(嗯,真的是类)。

import pytest

assert 2.2 == pytest.approx(2.3)
# fails, default is ± 2.3e-06
assert 2.2 == pytest.approx(2.3, 0.1)
# passes

# also works the other way, in case you were worried:
assert pytest.approx(2.3, 0.1) == 2.2
# passes

文档在这里

于 2016-09-21T18:05:33.563 回答
49

您必须为您指定“几乎”的内容:

assert abs(x-y) < 0.0001

应用于元组(或任何序列):

def almost_equal(x,y,threshold=0.0001):
  return abs(x-y) < threshold

assert all(map(almost_equal, zip((1.32, 2.4), i_return_tuple_of_two_floats())
于 2011-12-19T10:44:50.780 回答
37

如果您可以访问 NumPy,它具有很好的浮点比较功能,已经与numpy.testing.

然后您可以执行以下操作:

numpy.testing.assert_allclose(i_return_tuple_of_two_floats(), (1.32, 2.4))
于 2013-04-18T20:58:25.187 回答
17

这些答案已经存在了很长时间,但我认为最简单也是最易读的方法是使用 unittest ,因为它有很多不错的断言,而不将其用于测试结构。

获取断言,忽略 unittest.TestCase 的其余部分

(基于这个答案

import unittest

assertions = unittest.TestCase('__init__')

做一些断言

x = 0.00000001
assertions.assertAlmostEqual(x, 0)  # pass
assertions.assertEqual(x, 0)  # fail
# AssertionError: 1e-08 != 0

实现原题的自动解包测试

只需使用 * 来解压缩您的返回值,而无需引入新名称。

i_return_tuple_of_two_floats = lambda: (1.32, 2.4)
assertions.assertAlmostEqual(*i_return_tuple_of_two_floats())  # fail
# AssertionError: 1.32 != 2.4 within 7 places
于 2016-06-08T14:45:33.457 回答
12

就像是

assert round(x-y, 5) == 0

这就是unittest所做的

对于第二部分

assert all(round(x-y, 5) == 0 for x,y in zip((1.32, 2.4), i_return_tuple_of_two_floats()))

可能更好地将其包装在一个函数中

def tuples_of_floats_are_almost_equal(X, Y):
    return all(round(x-y, 5) == 0 for x,y in zip(X, Y))

assert tuples_of_floats_are_almost_equal((1.32, 2.4), i_return_tuple_of_two_floats())
于 2011-12-19T10:45:55.453 回答
11

如果你想要一些不仅适用于浮点数而且例如小数的东西,你可以使用 python 的math.isclose()

# - rel_tol=0.01` is 1% difference tolerance.
assert math.isclose(actual_value, expected_value, rel_tol=0.01)
于 2019-02-07T15:21:23.093 回答
4

我会使用nose.tools。它与 py.test 运行器配合得很好,并且还有其他同样有用的断言——assert_dict_equal()、assert_list_equal() 等。

from nose.tools import assert_almost_equals
assert_almost_equals(x, y, places=7) #default is 7 
于 2016-06-15T22:00:23.793 回答
1

可以只使用 round()

a, b = i_return_tuple_of_two_floats()
assert (1.32, 2.4) == round(a,2), round(b,1)
于 2021-08-21T18:40:50.190 回答