2011-12-19 13 views
44

Come fare assert almost equal con py.test per carri senza ricorrere a qualcosa di simile:pytest: affermare quasi uguale

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

Più in particolare, sarà utile conoscere una soluzione ordinata per confrontare rapidamente le coppie di galleggiante, senza estrarli:

assert (1.32, 2.4) == i_return_tuple_of_two_floats() 
+3

py.test ora ha una caratteristica che fa questo. – dbn

+0

Vedere [questa risposta] (https://stackoverflow.com/a/39623614/5353461) per una descrizione di quella funzione –

risposta

75

ho notato che questa domanda ha chiesto espressamente su py.test. py.test 3.0 include una funzione approx() (beh, davvero di classe) che è molto utile per questo scopo.

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 documentazione è qui: http://doc.pytest.org/en/latest/builtin.html#pytest.approx

+5

Bello! Inoltre ha trovato che funziona anche per sequenze di numeri, ad es. 'assert [0.1 + 0.2, 0.2 + 0.4] == pytest.approx ([0.3, 0.6])' –

+2

@Mr Kriss E anche per dicts: 'assert {'a': 0.1 + 0.2} == pytest.approx ({'a': 0.3}) ' –

+2

Questa dovrebbe essere la risposta accettata. – jstol

35

si dovrà specificare ciò che è "quasi" per voi:

assert abs(x-y) < 0.0001 

da applicare a tuple (o qualsiasi sequenza):

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()) 
+1

La domanda chiede come fare "senza ricorrere a qualcosa di simile" questo – endolith

+0

interpreto "qualcosa come questo "come un'espressione ripetitiva e scomoda come' x - d <= y <= x + d', sembra che sia quello che intendeva anche OP. Se non desideri specificare esplicitamente la soglia per "quasi", vedi la risposta di @ jiffyclub. – yurib

+2

py.test ora ha una funzione che fa questo. Ho aggiunto una risposta per discuterne. – dbn

11

Qualcosa di simile

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

Questo è ciò che unittest fa

Per la seconda parte

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

Probabilmente è meglio avvolgere quello in una funzione

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()) 
6

Queste risposte sono state utilizzate per un lungo periodo di tempo, ma penso che il più semplice e anche modo più leggibile è quello di utilizzare unittest per la sua many nice assertions senza usarlo per la struttura di test.

Get affermazioni, ignorare resto unittest.TestCase

(sulla base di this answer)

import unittest 

assertions = unittest.TestCase('__init__') 

fare alcune affermazioni

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

Implementare test di auto-disimballaggio domande originali

Basta usare * per decomprimere il valore restituito senza needi ng per introdurre nuovi nomi.

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 
2

Io userei il naso. Strumenti. Si gioca bene con py.test corridore e hanno altri altrettanto utile afferma - assert_dict_equal(), assert_list_equal(), ecc

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

Oltre a pytest ha un'opzione per questo non considero una buona opzione aggiungere una depurazione extra (in questo caso, un intero framwork di test) solo per questo. –