Pytest:断言几乎相等

如何使用pytest为浮点数执行assert almost equal,而不求助于以下内容:

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

更具体地说,它将有助于了解一个整洁的解决方案,快速比较浮点数对,而不拆封它们:

assert (1.32, 2.4) == i_return_tuple_of_two_floats()
117044 次浏览

你必须指明什么是“几乎”;对你:

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())
< p > 更新:
pytest.approx在2016年作为pytest v3.0.0的一部分发布。
这个答案早于它,使用这个if:

  • 你没有pytest AND的最新版本
  • 你了解浮点精度和它对你的用例的影响。

对于几乎所有常见场景,使用 pytest.approx as suggest in answer.

类似的

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())

如果你可以访问NumPy,它有很棒的浮点比较函数,已经与numpy.testing进行了成对比较。

然后你可以这样做:

numpy.testing.assert_allclose(i_return_tuple_of_two_floats(), (1.32, 2.4))

这些答案已经存在很长一段时间了,但我认为最简单也是最易读的方法是使用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

我会用鼻子工具。它可以很好地使用py。测试运行器和其他同样有用的断言- assert_dict_equal(), assert_list_equal()等。

from nose.tools import assert_almost_equals
assert_almost_equals(x, y, places=7) #default is 7

我注意到这个问题特别提到了pytest。pytest 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

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

# - rel_tol=0.01` is 1% difference tolerance.
assert math.isclose(actual_value, expected_value, rel_tol=0.01)

可以直接使用round()

a, b = i_return_tuple_of_two_floats()
assert (1.32, 2.4) == round(a,2), round(b,1)