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.