pytest: assert almost equal

后端 未结 7 1357
时光说笑
时光说笑 2020-12-24 03:55

How to do assert almost equal with py.test for floats without resorting to something like:

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


        
相关标签:
7条回答
  • 2020-12-24 04:38

    Something like

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

    That is what unittest does

    For the second part

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

    Probably better to wrap that in a function

    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())
    
    0 讨论(0)
  • 2020-12-24 04:42

    You will have to specify what is "almost" for you:

    assert abs(x-y) < 0.0001
    

    to apply to tuples (or any sequence):

    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())
    
    0 讨论(0)
  • 2020-12-24 04:42

    These answers have been around for a long time, but I think the easiest and also most readable way is to use unittest for it's many nice assertions without using it for the testing structure.

    Get assertions, ignore rest of unittest.TestCase

    (based on this answer)

    import unittest
    
    assertions = unittest.TestCase('__init__')
    

    Make some assertions

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

    Implement original questions' auto-unpacking test

    Just use * to unpack your return value without needing to introduce new names.

    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
    
    0 讨论(0)
  • 2020-12-24 04:42

    If you want something that works not only with floats but for example Decimals you can use python's math.isclose:

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

    Docs - https://docs.python.org/3/library/math.html#math.isclose

    0 讨论(0)
  • 2020-12-24 04:48

    I'd use nose.tools. It plays well with py.test runner and have other equally useful asserts - assert_dict_equal(), assert_list_equal(), etc.

    from nose.tools import assert_almost_equals
    assert_almost_equals(x, y, places=7) #default is 7 
    
    0 讨论(0)
  • 2020-12-24 04:55

    I noticed that this question specifically asked about py.test. py.test 3.0 includes an approx() function (well, really class) that is very useful for this purpose.

    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
    

    The documentation is here: https://docs.pytest.org/en/latest/reference.html#pytest-approx

    0 讨论(0)
提交回复
热议问题