Python unittest的assertDictContainsSubset推荐替代方案

Alp*_*a14 24 python unit-testing python-3.x

我在用unittest编写的Python中有一些测试.我想检查一下我的一些词典至少包含某些属于某些值的属性.如果有额外的值,那就没问题了.assertDictContainsSubset将是完美的,除了它已被弃用.是否有更好的事情我应该使用或者我应该递归断言内容是否相等,如果它们在目标字典中?

文档建议使用addTypeEqualityFunc,但我确实想assertEqual在某些情况下使用正常的dicts.

And*_*son 12

如果您正在测试dict A是否是dict B的子集,我想我会编写一个函数,试图从dict B中提取dict A的内容,然后创建一个新的dict C然后assertEqual(A,C).

def extractDictAFromB(A,B):
    return dict([(k,B[k]) for k in A.keys() if k in B.keys()])
Run Code Online (Sandbox Code Playgroud)

那么你可以做到

assertEqual(A,extractDictAFromB(A,B))
Run Code Online (Sandbox Code Playgroud)


Bor*_*ris 12

Python 3.9+ 上,使用字典联合运算符

改变

assertDictContainsSubset(a, b)
Run Code Online (Sandbox Code Playgroud)

assertEqual(b, b | a)
Run Code Online (Sandbox Code Playgroud)

在旧版本的 Python 上,将其更改为

assertEqual(b, {**b, **a})
Run Code Online (Sandbox Code Playgroud)

请注意参数的顺序assertDictContainsSubset将“较大的”字典 ( b)放在第二位,然后将子集 ( a) 放在第一位,但将较大的字典 ( b) 放在第一位更有意义(这就是为什么首先assertDictContainsSubset被删除的原因)。

这将创建bthen 迭代的副本a,将任何键设置为它们的值 ina然后将结果与原始结果进行比较b。如果您可以添加ato 的所有键/值b并且仍然具有相同的字典,则意味着a不包含任何不在其中的键,b并且它包含的所有键都具有与 in 相同的值b,即是一a个子集的b

  • @PaulPrice [`assertDictEqual`的文档](https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertDictEqual) 说“默认情况下,此方法将用于比较调用中的字典`assertEqual()`”和[另外](https://docs.python.org/3/library/unittest.html#unittest.TestCase.addTypeEqualityFunc)“通常不需要直接调用这些方法”。 (5认同)

Tae*_*ung 9

扩展@bman 的答案,利用类集合对象的比较运算符作为子集运算符重载,您可以使用assertGreaterEqual(可以说)更好的错误消息。

比较两个测试:

import unittest

class SubsetTestCase(unittest.TestCase):
    def test_dict_1(self):
        a = {1: 1, 2: 2}
        b = {1: 2}
        self.assertTrue(a.items() >= b.items())

    def test_dict_2(self):
        a = {1: 1, 2: 2}
        b = {1: 2}
        self.assertGreaterEqual(a.items(), b.items())

unittest.main()
Run Code Online (Sandbox Code Playgroud)

结果是:

======================================================================
FAIL: test_dict_1 (__main__.SubsetTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 9, in test_dict_1
    self.assertTrue(a.items() >= b.items())
AssertionError: False is not true

======================================================================
FAIL: test_dict_2 (__main__.SubsetTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 15, in test_dict_2
    self.assertGreaterEqual(a.items(), b.items())
AssertionError: dict_items([(1, 1), (2, 2)]) not greater than or equal to dict_items([(1, 2)])

----------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

使用assertGreaterEqual,您可以从错误消息中看到两个字典的内容。


bma*_*man 6

Andrew 提供了一个使用assertEqual. 但是,了解两种更简洁的替代解决方案对未来的读者很有用。第一个使用issubset集合的方法:

assert set(A.items()).issubset(set(B.items()))
Run Code Online (Sandbox Code Playgroud)

但是还有另一种更简单的 Pythonic 方式来做到这一点:

set(A.items()) <= set(B.items())
Run Code Online (Sandbox Code Playgroud)

第二种解决方案的缺陷是您不知道子集中缺少超集的哪些键。

但是,如果您的值中包含不可散列的变量(例如dict),则这两种解决方案都会失败。

  • @OlivierMelançon 你不需要 `set()`,因为 `dict.items()` 已经是“类似集合”了。请参阅:https://docs.python.org/3/library/stdtypes.html#dict-views (2认同)