web-dev-qa-db-ja.com

Pythonのdoctest-packageを使用して辞書の同等性をテストするにはどうすればよいですか?

辞書を出力する関数のdoctestを書いています。 doctestは次のようになります

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

私がそれを実行すると、それは失敗します

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

この失敗の原因についての私の最もよい推測は、doctestが辞書の同等性をチェックしていないということですが、__repr__平等。 この投稿 は、doctestをだまして辞書の同等性をチェックさせる方法があることを示しています。これどうやってするの?

39
Emmett Butler

Doctestは、__repr__の同等性自体をチェックせず、出力が完全に同じであることをチェックするだけです。印刷されるものが同じ辞書で同じになるようにする必要があります。あなたはこのワンライナーでそれをすることができます:

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

ソリューションのこのバリエーションはよりクリーンかもしれませんが:

>>> my_function() == {'this': 'is', 'a': 'dictionary'}
True
26
Claudiu

もう1つの良い方法は、(標準ライブラリの)pprintを使用することです。

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

そのソースコードによると、それはあなたのために口述を分類しています:

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

items = _sorted(object.items())
39
charlax

私はこれを使うことになった。ハッキーですが、機能します。

>>> p = my_function()
>>> {'this': 'is', 'a': 'dictionary'} == p
True
14
Emmett Butler

dict.items()を使用してリストに変換し、並べ替えます...

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

Doctest内にunittest.TestCaseクラスのインスタンスを作成し、それを使用して辞書を比較できます。

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

注:このアプローチは、2つの辞書間の差分を表示するため、単に辞書が等しいかどうかを確認するよりも優れています。

そのほとんどはすでにここで述べられています..とにかくJSYK:doctestドキュメントに専用のセクションがあります:

https://docs.python.org/3.5/library/doctest.html#warnings

1
iago-lito

任意にネストされたデータをテストするときに、doctestsで deepdiff パッケージを使用すると便利であることがわかりました。例えば:

def something_complicated():
    """
    >>> from deepdiff import DeepDiff
    >>> DeepDiff(something_complicated(),
    ...          {'expected': {'output': ['a', 'b', 'c']}},
    ...          ignore_order=True)
    {}
    """
    items = ['a', 'b', 'c']
    random.shuffle(items)
    return {'expected': {'output': items}}
0
brianmaissy