2013-03-21 29 views
27

Tôi đang viết một tài liệu cho một hàm xuất ra từ điển. Các doctest trông giống nhưLàm cách nào để kiểm tra sự bình đẳng từ điển với gói doctest của Python?

>>> my_function() 
{'this': 'is', 'a': 'dictionary'} 

Khi tôi chạy nó, nó không thành công với

Expected: 
    {'this': 'is', 'a': 'dictionary'} 
Got: 
    {'a': 'dictionary', 'this': 'is'} 

đoán tốt nhất của tôi như là nguyên nhân của sự thất bại này là doctest không kiểm tra bình đẳng từ điển, nhưng __repr__ bình đẳng. This post chỉ ra rằng có một số cách để lừa doctest vào kiểm tra bình đẳng từ điển. Tôi có thể làm cái này như thế nào?

+0

từ dict là không có thứ tự, bạn không thể sử dụng dict như nó được. bạn phải chuyển đổi nó thành một đối tượng được đặt hàng – ornoone

+0

Các câu trả lời được liệt kê dưới đây đều nằm trong tài liệu doctest: http://docs.python.org/2/library/doctest.html#warnings –

+0

@ornoone Nhưng tại sao? Họ là những đối tượng bình đẳng, đó là những gì doctest nên được kiểm tra. – endolith

Trả lời

19

Doctest không kiểm tra số __repr__ bình đẳng, nó chỉ kiểm tra xem kết quả có giống hệt nhau hay không. Bạn phải đảm bảo rằng mọi thứ được in sẽ giống nhau cho cùng một từ điển. Bạn có thể làm điều đó với một-liner:

>>> sorted(my_function().items()) 
[('a', 'dictionary'), ('this', 'is')] 

Mặc dù sự thay đổi này trên giải pháp của bạn có thể là sạch hơn:

>>> my_function() == {'this': 'is', 'a': 'dictionary'} 
True 
+2

Giải pháp của bạn là sạch hơn nhưng nó sẽ không cho bạn biết những gì my_function thực sự đánh giá. – jQwierdy

+0

giải pháp pprint trông sạch hơn nhiều, xem câu trả lời của charlax –

+1

nhưng nếu đó là một ví dụ tài liệu và tôi muốn hiển thị đầu vào thực tế và đầu ra thực tế? Có cách nào để có được nó để kiểm tra bình đẳng thay vì dây chính xác? – endolith

2

lượt nó thành một danh sách qua dict.items() và sau đó sắp xếp nó ...

>>> l = my_function().items() 
>>> l.sort() 
>>> l 
[('a', 'dictionary'), ('this', 'is')] 
+0

hoặc như một lớp lót: 'được sắp xếp (my_function(). Items())' – hardmooth

12

tôi đã kết thúc sử dụng này. Hacky, nhưng nó hoạt động.

>>> p = my_function() 
>>> {'this': 'is', 'a': 'dictionary'} == p 
True 
+3

Tôi không nghĩ rằng đó là hacky (mặc dù tôi muốn viết 'p == {etc}') - đó là kỹ thuật được đề xuất đầu tiên trong phần có liên quan của [tài liệu] (http://docs.python.org/3/library/doctest.html # cảnh báo). – DSM

+5

tại sao không phải 'my_function() == {'this': 'is', 'a': 'dictionary'}'? – endolith

+0

Những bất lợi ở đây là khi xác nhận không thành công, bạn không biết khóa nào, giá trị chính xác là sai. Giải pháp với 'pprint' sẽ hiển thị một sự khác biệt hữu ích. – geekQ

34

Một cách tốt là sử dụng pprint (trong thư viện tiêu chuẩn).

>>> import pprint 
>>> pprint.pprint({"second": 1, "first": 0}) 
{'first': 0, 'second': 1} 

Theo mã nguồn của nó, nó sắp xếp dicts cho bạn:

http://hg.python.org/cpython/file/2.7/Lib/pprint.py#l158

items = _sorted(object.items()) 
+4

nó sẽ đẹp, nhưng python devs [không khuyến nghị điều này] (https://bugs.python.org/issue20310) vì chúng không đảm bảo tính ổn định của pprint trên các phiên bản. – max

+0

cũng, giải pháp này nhất thiết phải làm việc cho các kiểu dữ liệu khác (chẳng hạn như tập hợp). – hardmooth

+0

Lợi thế ở đây là khi xác nhận không thành công, 'pprint' sẽ hiển thị một sự khác biệt rõ ràng. Nếu 'pprint' thực hiện thay đổi giữa phiên bản Python, tốt, chúng ta cần phải điều chỉnh các thử nghiệm của chúng tôi hoặc chỉ cần lặp lại việc thực hiện trong mã của chúng tôi để giữ cho nó ổn định. – geekQ

1

Bạn có thể tạo một thể hiện của unittest.TestCase lớp bên doctests của bạn, và sử dụng nó để so sánh các từ điển:

def my_function(x): 
    """ 
    >>> from unittest import TestCase 
    >>> t = TestCase() 

    >>> t.assertDictEqual(
    ...  my_function('a'), 
    ...  {'this': 'is', 'a': 'dictionary'} 
    ...) 

    >>> t.assertDictEqual(
    ...  my_function('b'), 
    ...  {'this': 'is', 'b': 'dictionary'} 
    ...) 

    """ 
    return {'this': 'is', x: 'dictionary'} 

Lưu ý: phương pháp này tốt hơn đơn giản là kiểm tra xem từ điển có bình đẳng không, vì nó sẽ hiển thị khác biệt giữa hai từ điển.

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