Как сделать assert almost equal
с py.test для поплавков, не прибегая к чему-то вроде:
assert x - 0.00001 <= y <= x + 0.00001
В частности, будет полезно знать изящное решение для быстрого сравнения пар поплавков, не распаковывая их:
assert (1.32, 2.4) == i_return_tuple_of_two_floats()
python
unit-testing
pytest
Владимир Келешев
источник
источник
Ответы:
Я заметил, что этот вопрос конкретно касается 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
Документация находится здесь: https://docs.pytest.org/en/latest/reference.html#pytest-approx
источник
assert [0.1 + 0.2, 0.2 + 0.4] == pytest.approx([0.3, 0.6])
assert {'a': 0.1+0.2} == pytest.approx({'a': 0.3})
assert [[0.1 + 0.2], [0.2 + 0.4]] == pytest.approx([[0.3], [0.6]])
приводит кTypeError
. Если обнаружено, что Numpy'snp.testing.assert_allclose([[0.1 + 0.2], [0.2 + 0.4]], [[0.3], [0.6]])
(см. Ответ ниже) действительно работает в этом случае.0.2 == pytest.approx(0.3, 0.1) # returns false; 0.2 == pytest.approx(0.3, abs=0.1) # returns true
Вам нужно будет указать, что для вас «почти»:
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())
источник
x - d <= y <= x+d
, похоже, это то, что имел в виду OP. Если вы не хотите явно указывать порог для «почти», см. Ответ @ jiffyclub.pytest.approx
. Писать собственную приближенную функцию - плохая идея. (Тот, что в этом ответе, даже не так хорош, как включенный.)Если у вас есть доступ к 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
источник
Что-то типа
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())
источник
Если вам нужно что-то, что работает не только с числами с плавающей запятой, но, например, с десятичными знаками, вы можете использовать python
math.isclose
:# - rel_tol=0.01` is 1% difference tolerance. assert math.isclose(actual_value, expected_value, rel_tol=0.01)
Документы - https://docs.python.org/3/library/math.html#math.isclose
источник
Я бы использовал нос. Он хорошо работает с бегуном 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
источник