Pytest: утверждают почти равные
Как сделать assert almost equal
с py.test для поплавков, не прибегая к чему-то вроде:
assert x - 0.00001 <= y <= x + 0.00001
В частности, будет полезно знать аккуратное решение для быстрого сравнения пар float, не распаковывая их:
assert (1.32, 2.4) == i_return_tuple_of_two_floats()
Ответы
Ответ 1
Я заметил, что этот вопрос специально задавался о 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
Ответ 2
Вам нужно будет указать, что для вас "почти":
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())
Ответ 3
Если у вас есть доступ к NumPy, у него есть отличные функции для сравнения с плавающей запятой, которые уже выполняют парное сравнение с numpy.testing
.
Тогда вы можете сделать что-то вроде:
numpy.testing.assert_allclose(i_return_tuple_of_two_floats(), (1.32, 2.4))
Ответ 4
Что-то вроде
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())
Ответ 5
Эти ответы существуют уже давно, но я думаю, что самый простой, а также наиболее читаемый способ - это использовать 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
Ответ 6
Я бы использовал nose.tools. Он хорошо работает с run.test runner и имеет другие одинаково полезные утверждения - assert_dict_equal(), assert_list_equal() и т.д.
from nose.tools import assert_almost_equals
assert_almost_equals(x, y, places=7) #default is 7