如何使用Python的doctest包测试字典平等性?

如何使用Python的doctest包测试字典平等性?,python,dictionary,doctest,Python,Dictionary,Doctest,我正在为输出字典的函数编写doctest。医生看起来像 >>> my_function() {'this': 'is', 'a': 'dictionary'} 当我运行它时,它会失败 Expected: {'this': 'is', 'a': 'dictionary'} Got: {'a': 'dictionary', 'this': 'is'} 我对失败原因的最佳猜测是,doctest没有检查字典的相等性,而是检查_; repr _;相等性。指示有某种方法

我正在为输出字典的函数编写doctest。医生看起来像

>>> my_function()
{'this': 'is', 'a': 'dictionary'}
当我运行它时,它会失败

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

我对失败原因的最佳猜测是,doctest没有检查字典的相等性,而是检查_; repr _;相等性。指示有某种方法可以欺骗doctest检查字典相等性。我如何才能做到这一点?

通过dict.items将其转换为列表,然后对其进行排序

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

最后我用了这个。哈奇,但它的工作

>>> p = my_function()
>>> {'this': 'is', 'a': 'dictionary'} == p
True
Doctest本身不检查_; repr__;相等,它只检查输出是否完全相同。你必须确保在同一本词典中打印的内容是相同的。您可以使用此一行程序执行此操作:

>>> sorted(my_function().items())
[('a', 'dictionary'), ('this', 'is')]
尽管您的解决方案中的此变体可能更干净:

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

另一个好方法是在标准库中使用pprint

>>> import pprint
>>> pprint.pprint({"second": 1, "first": 0})
{'first': 0, 'second': 1}
根据它的源代码,它是为你分类的:


您可以在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'}

注意:这种方法比简单地检查字典是否相等要好,因为它将显示两个字典之间的差异。

这里已经提到了大部分。。无论如何,JSYK:doctest文档中有一个专门的部分:


我发现在测试任意嵌套的数据时,在doctests中使用该包很有用。例如:

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

由于dict是无序的,所以不能按原样使用dict。您必须将其转换为有序对象下面列出的答案都在doctest文档中:@ornoone但是为什么?它们是相等的对象,这是doctest应该检查的。正如在接受答案中所说的,检查的是两个对象的repr,而不是它们的内容。自从雷普拉reprb doctest认为您的对象是不同的。如果a==b正常,则发生事件。我认为这是因为doctest在doc中,应该很容易阅读,并且通过repr检查,它是可读的。我不认为这是有问题的,尽管我会写p={etc}-这是相关章节中第一个推荐的技术。为什么我的函数=={'this':'is','a':'dictionary}?这里的缺点是一旦断言失败,您不知道哪些键、值是错误的。使用pprint的解决方案将显示一个有用的差异。您的解决方案更清晰,但它无法告诉您my_函数的实际计算结果。pprint解决方案看起来更清晰,请参阅charlax的回答,但如果它是一个文档示例,并且我希望显示真实的输入和输出,该怎么办?有没有办法让它检查相等性而不是精确的字符串?您给出的第二个变体非常适合我的简单doctest。谢谢pprint解决方案并不总是适用于set doctest-没有保证顺序。如果您想知道它的计算结果,您可以使用my_function=={'this':'is','a':'dictionary'}或my_function。这很好,但是python开发人员不能保证跨版本的pprint稳定性。此外,此解决方案必须适用于其他数据类型,如set。优点是一旦断言失败,pprint将显示一个有用的差异。如果pprint实现在Python版本之间发生变化,那么,我们需要调整测试,或者只是在代码中复制实现以保持稳定。或者作为一行代码:sorted my_function.items
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}}