it-swarm-pt.tech

pytest: afirma quase igual

Como fazer assert almost equal com py.test para floats sem recorrer a algo como:

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

Mais especificamente, será útil conhecer uma solução simples para comparar rapidamente os pares de float, sem desempacotá-los:

assert (1.32, 2.4) == i_return_Tuple_of_two_floats()
83
Halst

Notei que esta pergunta perguntou especificamente sobre py.test. O py.test 3.0 inclui uma função approx() (bem, realmente classe) que é muito útil para este propósito.

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

A documentação está aqui: https://docs.pytest.org/en/latest/reference.html#pytest-approx

142
dbn

Você terá que especificar o que é "quase" para você:

assert abs(x-y) < 0.0001

para aplicar a tuplas (ou qualquer sequência):

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

Se você tiver acesso ao NumPy, ele terá ótimas funções para comparação de ponto flutuante que já fazem comparação emparelhada com numpy.testing .

Então você pode fazer algo como:

numpy.testing.assert_allclose(i_return_Tuple_of_two_floats(), (1.32, 2.4))
27
jiffyclub

Algo como

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

Isso é o que unittest faz

Para a segunda parte

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

Provavelmente melhor para embrulhar isso em uma função

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())
11
John La Rooy

Essas respostas existem há muito tempo, mas acho que a maneira mais fácil e mais legível é usar o unittest para ele muitas afirmações do Nice sem usá-lo para a estrutura de teste.

Obtenha asserções, ignore o resto do unittest.TestCase

(baseado em esta resposta )

import unittest

assertions = unittest.TestCase('__init__')

Faça algumas afirmações

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

Implementar o teste de desembalagem automática das perguntas originais

Apenas use * para descompactar seu valor de retorno sem precisar introduzir novos nomes.

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
8
KobeJohn

Eu usaria nose.tools. Ele joga bem com o py.test runner e tem outras afirmações igualmente úteis - assert_dict_equal (), assert_list_equal (), etc.

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

Se você quer algo que funciona não apenas com floats, mas por exemplo Decimais, você pode usar o math.isclose de python:

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

Documentos - https://docs.python.org/3/library/math.html#math.isclose

0
validname