webentwicklung-frage-antwort-db.com.de

pytest: fast gleich behaupten

Wie man assert almost equal mit py.test für Floats macht, ohne auf etwas wie zu greifen:

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

Insbesondere ist es hilfreich, eine ordentliche Lösung für den schnellen Vergleich von Floatpaaren zu kennen, ohne sie auszupacken:

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

Mir ist aufgefallen, dass diese Frage speziell nach py.test gestellt wurde. py.test 3.0 enthält eine approx()-Funktion (naja, wirklich Klasse), die für diesen Zweck sehr nützlich ist.

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

Die Dokumentation ist hier: https://docs.pytest.org/de/latest/reference.html#pytest-approx

142
dbn

Sie müssen angeben, was für Sie "fast" ist:

assert abs(x-y) < 0.0001

für Tupel (oder eine beliebige Sequenz) gelten:

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

Wenn Sie auf NumPy zugreifen können, gibt es großartige Funktionen für den Vergleich von Fließkommazahlen, die bereits einen paarweisen Vergleich mit numpy.testing durchführen.

Dann kannst du so etwas tun:

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

So etwas wie

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

Das ist es, was unittest tut

Für den zweiten Teil

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

Wahrscheinlich besser, das in eine Funktion zu packen

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

Diese Antworten gibt es schon lange, aber ich denke, der einfachste und auch lesbarste Weg ist, sie nur für viele Nice Assertions zu verwenden, ohne sie für die Teststruktur zu verwenden.

Holen Sie sich Assertionen, ignorieren Sie den Rest der unittest.TestCase

(basierend auf diese Antwort )

import unittest

assertions = unittest.TestCase('__init__')

Machen Sie einige Behauptungen

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

Führen Sie den Test zum automatischen Auspacken der ursprünglichen Fragen durch

Verwenden Sie einfach *, um Ihren Rückgabewert zu entpacken, ohne neue Namen eingeben zu müssen.

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

Ich würde Nasentools verwenden. Es spielt gut mit py.test runner und hat andere, ebenso nützliche Asserts - assert_dict_equal (), assert_list_equal () usw.

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

Wenn Sie etwas möchten, das nicht nur mit Floats, sondern beispielsweise mit Decimals funktioniert, können Sie den math.isclose von python verwenden:

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

Text & Tabellen - https://docs.python.org/3/library/math.html#math.isclose

0
validname