pytest: लगभग बराबर बराबर


145

assert almost equalबिना कुछ का सहारा लिए झांकियों के लिए py.test के साथ कैसे करें :

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

अधिक विशेष रूप से यह फ्लोट के जोड़े की जल्दी से तुलना के लिए एक साफ समाधान जानने के लिए उपयोगी होगा, उन्हें अनपैक किए बिना:

assert (1.32, 2.4) == i_return_tuple_of_two_floats()

3
py.test में अब एक फीचर है जो ऐसा करता है।
18

उस सुविधा के विवरण के लिए यह उत्तर देखें
टॉम हेल

जवाबों:


232

मैंने देखा कि यह प्रश्न विशेष रूप से py.test के बारे में पूछा गया था। py.test 3.0 में एक approx()फ़ंक्शन (अच्छी तरह से, वास्तव में वर्ग) शामिल है जो इस उद्देश्य के लिए बहुत उपयोगी है।

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

प्रलेखन यहाँ है: https://docs.pytest.org/en/latest/reference.html#pytest-approx


12
अच्छा! यह भी पाया कि यह संख्याओं के अनुक्रम के लिए भी काम करता है जैसेassert [0.1 + 0.2, 0.2 + 0.4] == pytest.approx([0.3, 0.6])
मिस्टर क्रिश

4
@ एमआर क्रिश और यहां तक ​​कि डिक्ट्स के लिए:assert {'a': 0.1+0.2} == pytest.approx({'a': 0.3})
एंटनी हैचकिंस

4
यह सूचियों की सूची के लिए काम नहीं करता है: उदाहरण के लिए, assert [[0.1 + 0.2], [0.2 + 0.4]] == pytest.approx([[0.3], [0.6]])एक की ओर जाता है TypeError। अगर पाया गया कि नम्पी np.testing.assert_allclose([[0.1 + 0.2], [0.2 + 0.4]], [[0.3], [0.6]])(नीचे उत्तर देखें) ने इस मामले के लिए काम किया।
कर्ट पीक

43

आपको यह बताना होगा कि आपके लिए "लगभग" क्या है:

assert abs(x-y) < 0.0001

tuples (या किसी भी अनुक्रम) पर लागू करने के लिए:

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
सवाल पूछता है कि यह कैसे करना है "कुछ इस तरह का सहारा लिए बिना"
एंडोलिथ

मैं दोहराव और अजीब अभिव्यक्ति के रूप में "कुछ इस तरह" की व्याख्या करता हूं x - d <= y <= x+d, ऐसा लगता है कि ओपी का भी यही मतलब है। यदि आप स्पष्ट रूप से 'लगभग' के लिए सीमा निर्दिष्ट नहीं करना चाहते हैं, तो @ jiffyclub का उत्तर देखें।
युरिब

2
py.test में अब एक फीचर है जो ऐसा करता है। मैंने इस पर चर्चा करते हुए एक उत्तर जोड़ा है।
dbn

2
@ नीलगाय पृथ्वी पर इसे क्यों हटाया जाना चाहिए? अगर वहाँ स्पष्ट रूप से कुछ गड़बड़ है तो कृपया बताएं कि यह क्या है।
user2699

1
@ user2699 सवाल यह है कि यह कैसे करना है। पाइस्टेस्ट में इसे करने का सही तरीका उपयोग करना है pytest.approx। अपने स्वयं के अनुमानित कार्य को लिखना एक बुरा विचार है। (इस जवाब में एक भी शामिल के रूप में अच्छा नहीं है।)
नील जी

31

यदि आपके पास NumPy तक पहुंच है, तो इसके पास फ्लोटिंग पॉइंट तुलना के लिए महान कार्य हैं जो पहले से ही जोड़ीदार तुलना करते हैं numpy.testing

तब आप कुछ ऐसा कर सकते हैं:

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

11

कुछ इस तरह

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

यही कारण है कि है unittest करता है

दूसरे भाग के लिए

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

एक समारोह में लपेटने के लिए शायद बेहतर है

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

ये उत्तर लंबे समय से आसपास हैं, लेकिन मुझे लगता है कि सबसे आसान और सबसे पठनीय तरीका यह है कि परीक्षण संरचना के लिए इसका उपयोग किए बिना कई अच्छे अभिकथनों के लिए बिना उपयोग किए जाएं।

दावे प्राप्त करें, बाकी unittest.TestCase को अनदेखा करें

( इस जवाब पर आधारित )

import unittest

assertions = unittest.TestCase('__init__')

कुछ मुखर करें

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

मूल सवालों को ऑटो-अनपैकिंग टेस्ट लागू करें

नए नामों को प्रस्तुत करने की आवश्यकता के बिना अपने रिटर्न मान को अनपैक करने के लिए बस * का उपयोग करें।

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

यदि आप ऐसा कुछ चाहते हैं जो न केवल तैरने के साथ काम करे बल्कि उदाहरण के लिए दशमलव आप अजगर का उपयोग कर सकते हैं math.isclose:

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

डॉक्स - https://docs.python.org/3/library/math.html#math.isclose


यहाँ रिश्तेदार सहिष्णुता (या प्रतिशत अंतर) कुछ उपयोग मामलों में उपयोग करने के लिए सुविधाजनक है, उदाहरण के लिए।
करियोकी

3

मैं nose.tools का उपयोग करेंगे। यह py.test धावक के साथ अच्छी तरह से खेलता है और अन्य समान रूप से उपयोगी मुखर हैं - assert_dict_equal (), assert_list_equal (), आदि।

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

2
इसके अलावा पाइस्टेस्ट के पास इसके लिए एक विकल्प है, मैं इस बात पर विचार नहीं करता कि एक अच्छा विकल्प केवल इसके लिए एक अतिरिक्त चित्रण (इस मामले में, एक संपूर्ण परीक्षण फ्रेमवर्क) जोड़ें।
मार्क टुदुरि
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.