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에는 이제이를 수행하는 기능이 있습니다.
dbn

기능에 대한 설명은 이 답변 을 참조하십시오
Tom Hale

답변:


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])
Mrs Kriss

4
크리스 @Mr 그리고 심지어 dicts에 대한 :assert {'a': 0.1+0.2} == pytest.approx({'a': 0.3})
안토니 Hatchkins

4
목록 목록에는 작동하지 않습니다. 예를 들어로 assert [[0.1 + 0.2], [0.2 + 0.4]] == pytest.approx([[0.3], [0.6]])이어집니다 TypeError. Numpy 's np.testing.assert_allclose([[0.1 + 0.2], [0.2 + 0.4]], [[0.3], [0.6]])(아래 답변 참조) 가이 경우에 효과가 있음을 발견했습니다 .
커트 픽

43

"거의"항목을 지정해야합니다.

assert abs(x-y) < 0.0001

튜플 (또는 모든 순서)에 적용하려면 :

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
이 질문은 "어떤 것에 의지하지 않고"어떻게해야하는지 묻습니다
endolith

나는 "이것과 같은 것"을 반복적이고 어색한 표현으로 해석 x - d <= y <= x+d한다. 그것은 OP가 의미 한 것처럼 보인다. '거의'에 대한 임계 값을 명시 적으로 지정하지 않으려면 @jiffyclub의 답변을 참조하십시오.
yurib

2
py.test에는 이제이를 수행하는 기능이 있습니다. 그것에 대해 답변을 추가했습니다.
dbn

2
@NeilG 왜 지구상에서 이것을 삭제해야합니까? 분명히 문제가있는 경우 그 내용을 설명하십시오.
2699

1
@ user2699 문제는 pytest에서 이것을 수행하는 방법입니다. pytest에서 올바른 방법은을 사용하는 것 pytest.approx입니다. 대략적인 함수를 작성하는 것은 좋지 않습니다. (이 답변에있는 것은 포함 된 것만 큼 좋지 않습니다.)
Neil G

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

즉 무엇 유닛 테스트가 수행

두 번째 부분

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를 무시하십시오.

( 이 답변을 기반으로 )

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

float뿐만 아니라 Decimals와 같이 작동하는 것을 원한다면 Python을 사용할 수 있습니다 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


여기서 상대 허용 오차 (또는 백분율 차이)는 일부 사용 사례, 예를 들어 scienfific에서 사용하기 편리합니다.
Karioki

3

nose.tools를 사용합니다. py.test 러너와 잘 작동하며 assert_dict_equal (), assert_list_equal () 등 다른 유용한 assert가 있습니다.

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

2
pytest 외에도 이것에 대한 옵션이 있습니다. 좋은 옵션은 이것에 대해서만 여분의 depency (이 경우 전체 테스트 프레임 워크)를 추가하는 것으로 간주하지 않습니다.
Marc Tudurí 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.