2011-12-19 32 views
44

Làm thế nào để làm assert almost equal với py.test cho nổi mà không cần đến một cái gì đó như:pytest: khẳng định gần như bằng

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

Cụ thể hơn nó sẽ hữu ích để biết một giải pháp gọn gàng cho nhanh chóng so sánh cặp phao, mà không giải nén chúng:

assert (1.32, 2.4) == i_return_tuple_of_two_floats() 
+3

py.test bây giờ có một tính năng thực hiện điều này. – dbn

+0

Xem [câu trả lời này] (https://stackoverflow.com/a/39623614/5353461) để biết mô tả về đối tượng địa lý đó –

Trả lời

75

tôi nhận thấy rằng câu hỏi này đặc biệt yêu cầu về py.test. py.test 3.0 bao gồm một hàm approx() (tốt, thực sự là lớp) rất hữu ích cho mục đích này.

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 

Các tài liệu là ở đây: http://doc.pytest.org/en/latest/builtin.html#pytest.approx

+5

Tuyệt vời! Cũng tìm thấy nó hoạt động cho chuỗi các số quá, ví dụ: 'khẳng định [0.1 + 0.2, 0.2 + 0.4] == pytest.approx ([0.3, 0.6])' –

+2

@Mr Kriss Và ngay cả đối với người dicts: 'assert {'a': 0.1 + 0.2} == pytest.approx ({'a': 0.3}) ' –

+2

Đây phải là câu trả lời được chấp nhận. – jstol

35

bạn sẽ phải xác định là những gì "gần như" cho bạn:

assert abs(x-y) < 0.0001 

để áp dụng cho các bộ (hoặc bất kỳ trình tự):

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()) 
+1

Câu hỏi hỏi cách thực hiện "không cần sử dụng một cái gì đó như" này – endolith

+0

Tôi giải thích "một cái gì đó như thế này "như một biểu thức lặp đi lặp lại và lúng túng như' x - d <= y <= x + d', có vẻ như đó là ý nghĩa của OP. Nếu bạn không muốn chỉ định rõ ràng ngưỡng cho 'gần như', hãy xem câu trả lời của @ jiffyclub. – yurib

+2

py.test hiện có một tính năng thực hiện điều này. Tôi đã thêm một câu trả lời thảo luận về nó. – dbn

11

Something như

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

Đó là những gì unittest không

Đối với phần thứ hai

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

Có lẽ tốt hơn để bọc trong một hàm

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()) 
6

Những câu trả lời đã được khoảng một thời gian dài, nhưng tôi nghĩ dễ nhất và cũng là cách dễ đọc nhất là sử dụng unittest cho nó many nice assertions mà không sử dụng nó cho cấu trúc thử nghiệm.

Nhận khẳng định, bỏ qua phần còn lại của unittest.TestCase

(dựa trên this answer)

import unittest 

assertions = unittest.TestCase('__init__') 

Làm cho một số khẳng định

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

Thực hiện kiểm tra tự động giải nén câu hỏi ban đầu

Chỉ cần sử dụng * để giải nén giá trị trả lại của bạn mà không cần ng để giới thiệu tên mới.

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 
2

Tôi muốn sử dụng mũi.tools. Nó đóng tốt với Á hậu py.test và có không kém hữu ích khẳng định khác - assert_dict_equal(), assert_list_equal(), vv

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

Bên cạnh đó pytest có một tùy chọn cho điều này tôi không xem xét một lựa chọn tốt thêm một depency thêm (trong trường hợp này, một thử nghiệm toàn bộ framwork) chỉ cho việc này. –

Các vấn đề liên quan