Comment faire assert almost equal
avec py.test pour les floats sans avoir recours à quelque chose comme:
assert x - 0.00001 <= y <= x + 0.00001
Plus spécifiquement, il sera utile de connaître une solution soignée pour comparer rapidement des paires de float sans les décompresser:
assert (1.32, 2.4) == i_return_Tuple_of_two_floats()
J'ai remarqué que cette question concernait spécifiquement py.test. py.test 3.0 inclut une fonction approx()
(enfin, vraiment une classe) qui est très utile à cette fin.
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
La documentation est ici: https://docs.pytest.org/fr/latest/reference.html#pytest-approx
Vous devrez spécifier ce qui est "presque" pour vous:
assert abs(x-y) < 0.0001
appliquer aux n-uplets (ou n'importe quelle séquence):
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())
Si vous avez accès à NumPy, il dispose d'excellentes fonctions de comparaison par virgule flottante qui effectuent déjà une comparaison par paire avec numpy.testing
.
Ensuite, vous pouvez faire quelque chose comme:
numpy.testing.assert_allclose(i_return_Tuple_of_two_floats(), (1.32, 2.4))
Quelque chose comme
assert round(x-y, 5) == 0
C'est ce que unittest fait
Pour la deuxième partie
assert all(round(x-y, 5) == 0 for x,y in Zip((1.32, 2.4), i_return_Tuple_of_two_floats()))
Probablement mieux envelopper cela dans une fonction
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())
Ces réponses existent depuis longtemps, mais je pense que le moyen le plus simple et le plus lisible consiste à utiliser unittest pour son nombreuses affirmations de Nice sans l'utiliser pour la structure de test.
(basé sur cette réponse )
import unittest
assertions = unittest.TestCase('__init__')
x = 0.00000001
assertions.assertAlmostEqual(x, 0) # pass
assertions.assertEqual(x, 0) # fail
# AssertionError: 1e-08 != 0
Utilisez simplement * pour décompresser votre valeur de retour sans avoir à introduire de nouveaux noms.
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
J'utiliserais des outils nasaux. Il fonctionne bien avec le coureur py.test et a d'autres assertions tout aussi utiles - assert_dict_equal (), assert_list_equal (), etc.
from nose.tools import assert_almost_equals
assert_almost_equals(x, y, places=7) #default is 7
Si vous voulez quelque chose qui fonctionne non seulement avec float mais par exemple avec Decimals, vous pouvez utiliser le math.isclose
de python:
# - rel_tol=0.01` is 1% difference tolerance.
assert math.isclose(actual_value, expected_value, rel_tol=0.01)
Docs - https://docs.python.org/3/library/math.html#math.isclose