2013-03-21 39 views
27

Piszę doctest dla funkcji, która wyprowadza słownik. Doctest wyglądaJak przetestować równość słownikową za pomocą pakietu doctest pakietu Python?

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

Kiedy go uruchomić, nie jest on z

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

mój najlepszy przypuszczenie co do przyczyny tego niepowodzenia jest to, że nie jest sprawdzanie doctest słownika równości, ale __repr__ równość. This post wskazuje, że istnieje sposób na oszukiwanie procesu doctest w sprawdzaniu równości w słowniku. Jak mogę to zrobić?

+0

od dict jest nieuporządkowana, nie można użyć dict jak to jest. musisz przekształcić go w uporządkowany obiekt. – ornoone

+0

Poniższe odpowiedzi znajdują się w dokumentacji dokumentacji doctest: http://docs.python.org/2/library/doctest.html#warnings –

+0

@ornoone Ale dlaczego? Są to obiekty równe, to właśnie powinien sprawdzić doctest. – endolith

Odpowiedz

19

Doctest nie sprawdza __repr__ równości per se, to po prostu sprawdza, czy wyjście jest dokładnie taka sama. Musisz upewnić się, że wszystko, co zostanie wydrukowane, będzie takie samo dla tego samego słownika. Można to zrobić z tym jednym-liner:

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

Chociaż to wariacja na temat rozwiązania mogłyby być czystsze:

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

Twoje rozwiązanie jest czystsze, ale nie powie Ci, na co faktycznie oceniliśmy funkcję my_function. – jQwierdy

+0

rozwiązanie pprint wygląda znacznie czystsze, zobacz charlax za odpowiedź –

+1

ale co jeśli jest to przykład dokumentacja i chcę pokazać realne wejście i wyjście realistyczny? Czy istnieje sposób, aby uzyskać to, aby sprawdzić równość zamiast dokładnych ciągów? – endolith

2

przekształcić go w wykazie poprzez dict.items(), a następnie posortować je ...

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

lub jako jeden-liniowiec: 'sorted (my_function(). Items())' – hardmooth

12

skończyło się przy użyciu tego produktu. Hacky, ale działa.

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

Nie sądzę, że to jest hacky (chociaż napisałem 'p == {etc}) - to pierwsza zalecana technika w odpowiedniej sekcji [docs] (http://docs.python.org/3/library/doctest.html # ostrzeżenia). – DSM

+5

dlaczego nie 'my_function() == {'this': 'is', 'a': 'dictionary'}'? – endolith

+0

Wadą jest to, gdy asercja nie powiedzie się, nie wiesz, które klucze, wartości są dokładnie błędne. Rozwiązanie z 'pprint' pokazuje pomocną różnicę. – geekQ

34

Innym dobrym sposobem jest użycie pprint (w bibliotece standardowej).

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

Według jego kodu źródłowego, to sortowanie dicts dla Ciebie:

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

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

byłoby miło, ale python devs [nie polecaj tego] (https://bugs.python.org/issue20310), ponieważ nie gwarantują stabilności pprint w różnych wersjach. – max

+0

również to rozwiązanie musi działać dla innych typów danych (takich jak zestaw). – hardmooth

+0

Zaletą tutaj jest to, że gdy asercja się nie powiedzie, 'pprint' wyświetli różnicę helpl. Jeśli implementacja 'pprint' zmienia się między wersją Pythona, musimy dostosować nasze testy lub po prostu powielić implementację w naszym kodzie, aby zachować stabilność. – geekQ

1

Można utworzyć instancję unittest.TestCase klasy wewnątrz firmy doctests i używać go porównać słowniki:

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'} 

Uwaga: to podejście jest lepsze niż po prostu sprawdzanie, czy słowniki są równe, ponieważ pokazuje różnicę między dwoma słownikami.