pytest: neredeyse eşit iddia


145

assert almost equalŞöyle bir şeye başvurmadan şamandıralar için py.test ile nasıl yapılır :

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

Daha spesifik olarak, şamandıra çiftlerini, paketlerini açmadan hızlı bir şekilde karşılaştırmak için temiz bir çözüm bilmek yararlı olacaktır:

assert (1.32, 2.4) == i_return_tuple_of_two_floats()

3
py.test şimdi bunu yapan bir özelliğe sahiptir.
dbn

Bu özelliğin açıklaması için bu cevaba bakınız
Tom Hale

Yanıtlar:


232

Bu sorunun özellikle py.test hakkında sorduğunu fark ettim. py.test 3.0, approx()bu amaç için çok kullanışlı bir işlev (iyi, gerçekten sınıf) içerir.

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

Belgeler burada: https://docs.pytest.org/en/latest/reference.html#pytest-approx


12
Güzel! Ayrıca, örneğin sayı dizileri için de işe assert [0.1 + 0.2, 0.2 + 0.4] == pytest.approx([0.3, 0.6])
yaradı

4
@Mr Kriss Ve hatta dikte için:assert {'a': 0.1+0.2} == pytest.approx({'a': 0.3})
Antony Hatchkins

4
Bu liste listeleri için çalışmaz: örneğin, assert [[0.1 + 0.2], [0.2 + 0.4]] == pytest.approx([[0.3], [0.6]])a TypeError. np.testing.assert_allclose([[0.1 + 0.2], [0.2 + 0.4]], [[0.3], [0.6]])Bu durumda Numpy'nin (aşağıdaki cevaba bakınız) işe yaradığı tespit edilirse .
Kurt Peek

43

Sizin için neyin "neredeyse" olduğunu belirtmeniz gerekir:

assert abs(x-y) < 0.0001

tuples (veya herhangi bir sekans) uygulamak için:

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
Soru, bunun gibi bir şeye başvurmadan nasıl yapılacağını soruyor
endolith

"Böyle bir şeyi" tekrarlayan ve garip bir ifade olarak yorumluyorum x - d <= y <= x+d, OP'nin de anlamı bu gibi görünüyor. 'Neredeyse' için eşiği açıkça belirtmek istemiyorsanız, @ jiffyclub'ın cevabına bakınız.
yurib

2
py.test şimdi bunu yapan bir özelliğe sahiptir. Bunu tartışan bir cevap ekledim.
16:36 dbn

2
@NeilG Bu neden dünya üzerinde silinmeli? Açıkça yanlış olan bir şey varsa, lütfen ne olduğunu açıklayın.
user2699

1
@ user2699 Soru, bunun pytest'te nasıl yapılacağıdır. Pytest'te bunu yapmanın doğru yolu kullanmaktır pytest.approx. Kendi yaklaşık fonksiyonunuzu yazmak kötü bir fikirdir. (Bu cevaptaki kişi, dahil edilen kişi kadar iyi değildir.)
Neil G

31

NumPy'ye erişiminiz varsa, kayan nokta karşılaştırması için zaten çiftli karşılaştırma yapan harika işlevlere sahiptir numpy.testing.

Sonra şöyle bir şey yapabilirsiniz:

numpy.testing.assert_allclose(i_return_tuple_of_two_floats(), (1.32, 2.4))

11

Gibi bir şey

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

Yani ne unittest yapar

İkinci bölüm için

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

Muhtemelen bir fonksiyona sarmak daha iyidir

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

Bu cevaplar uzun zamandır var, ama en kolay ve en okunabilir yolun test yapısı için kullanmadan birçok güzel iddia için unittest kullanmak olduğunu düşünüyorum.

İddialar alın, unittest'in geri kalanını yok sayın.

( bu cevaba dayanarak )

import unittest

assertions = unittest.TestCase('__init__')

Bazı iddialarda bulunun

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

Orijinal soruların otomatik paket açma testini uygulayın

Yeni adlar eklemenize gerek kalmadan dönüş değerinizi açmak için * kullanın.

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

Sadece şamandıralarla değil, aynı zamanda Ondalık Sayılarla çalışan bir şey istiyorsanız, python'ları kullanabilirsiniz math.isclose:

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

Dokümanlar - https://docs.python.org/3/library/math.html#math.isclose


Burada nispi tolerans (veya yüzde farkı) bazı kullanım durumlarında, örneğin bilimsel olarak kullanım için uygundur.
Karioki

3

Burun kullanırım. Araçlar. Py.test koşucusu ile iyi oynar ve aynı derecede faydalı başka varsayımlara sahiptir - assert_dict_equal (), assert_list_equal (), vb.

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

2
Pytest bunun için bir seçenek var Ben sadece bunun için ekstra bir bağımlılık (bu durumda, bir bütün test çerçeve) eklemek iyi bir seçenek düşünmüyorum.
Marc Tudurí
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.