How do I test dictionary-equality with Python'

2019-01-17 19:52发布

I'm writing a doctest for a function that outputs a dictionary. The doctest looks like

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

When I run it, it fails with

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

My best guess as to the cause of this failure is that doctest isn't checking dictionary equality, but __repr__ equality. This post indicates that there's some way to trick doctest into checking dictionary equality. How can I do this?

6条回答
ら.Afraid
2楼-- · 2019-01-17 20:06

Doctest doesn't check __repr__ equality, per se, it just checks that the output is exactly the same. You have to ensure that whatever is printed will be the same for the same dictionary. You can do that with this one-liner:

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

Although this variation on your solution might be cleaner:

>>> my_function() == {'this': 'is', 'a': 'dictionary'}
True
查看更多
聊天终结者
3楼-- · 2019-01-17 20:09

turn it into a list via dict.items() and then sort it ...

>>> l = my_function().items()
>>> l.sort()
>>> l
[('a', 'dictionary'), ('this', 'is')]
查看更多
混吃等死
4楼-- · 2019-01-17 20:13

You can create an instance of unittest.TestCase class inside your doctests, and use it to compare dictionaries:

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

Note: this approach is better than simply checking if dictionaries are equal, because it will show diff between the two dictionaries.

查看更多
地球回转人心会变
5楼-- · 2019-01-17 20:14

Another good way is to use pprint (in the standard library).

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

According to its source code, it's sorting dicts for you:

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

items = _sorted(object.items())
查看更多
Evening l夕情丶
6楼-- · 2019-01-17 20:18

I ended up using this. Hacky, but it works.

>>> p = my_function()
>>> {'this': 'is', 'a': 'dictionary'} == p
True
查看更多
闹够了就滚
7楼-- · 2019-01-17 20:23

Most of it has been already said here.. anyway JSYK: there is a dedicated section in doctest documentation:

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

查看更多
登录 后发表回答