如果 dicts 可以通过‘ = =’进行比较,为什么需要 assertDictequals?

老实说,我一直使用 assertDictEqual,因为有时当我没有使用它,我得到的信息,平等的字母是不一样的。

但是... ... 我知道字符可以由 ==操作员进行比较:

>>> {'a':1, 'b':2, 'c': [1,2]} == {'b':2, 'a':1, 'c': [1,2]}
True

在哪里我实际上可能需要 assertDictEqual

110817 次浏览

Basically, it allows unittest to give you more information about why the test failed ("diagnostics", to use the language from "Growing Object-Oriented Software Guided by Tests" by Steve Freeman and Nat Pryce). Compare these two tests:

import unittest




class DemoTest(unittest.TestCase):


D1 = {'a': 1, 'b': 2, 'c': [1, 2]}
D2 = {'a': 1, 'b': 2, 'c': [1]}


def test_not_so_useful(self):
self.assertTrue(self.D1 == self.D2)


def test_useful(self):
self.assertDictEqual(self.D1, self.D2)




if __name__ == "__main__":
unittest.main()

And their outputs:

======================================================================
FAIL: test_not_so_useful (__main__.DemoTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "path/to/file.py", line 10, in test_not_so_useful
self.assertTrue(self.D1 == self.D2)
AssertionError: False is not true

vs.

======================================================================
FAIL: test_useful (__main__.DemoTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "path/to/file.py", line 13, in test_useful
self.assertDictEqual(self.D1, self.D2)
AssertionError: {'a': 1, 'b': 2, 'c': [1, 2]} != {'a': 1, 'b': 2, 'c': [1]}
- {'a': 1, 'b': 2, 'c': [1, 2]}
?                         ---


+ {'a': 1, 'b': 2, 'c': [1]}

In the latter, you can see exactly what the difference was, you don't have to work it out yourself. Note that you can just use the standard assertEqual instead of assertDictEqual, with the same result; per the docs

...it’s usually not necessary to invoke these methods directly.

I assume this is in the context of unit testing. The assertDictEqual method will not only compare the dicts and evaluate to True or False but can give you additional information, such as the exact differences between the two dicts.

Moreover, in a good IDE the unit tests will integrate nicely. You can just add a TestCase, use assertDictEqual and the IDE will find and run the test for you. The output is then displayed in an easy to read format. This can save you a lot of boilerplate code.

I would be very interested in a case where two equal dicts are not equal when compared with ==.

This is part of a broader question:

Why does unittest have all the special asserts at all?

The answer is that the primary job of the UnitTest assert* methods is to give you meaningful output when a test fails. Take a look at the unittest module code -- that really is mostly what they do (only what they do?)

Given that Python is a dynamic language with easy introspection, why bother will all that? And the answer is "because unittest was ported from the Java junit package, and that's how they did it in Java" (and probably had to, given how much harder or impossible it is to introspect at run time).

So my recommendation: unless you are writing tests for the standard library, don't use unittest at all -- all it does is get in the way. I use pytest. nose may be a good option as well. It make it quicker and easier to write tests, and you get excellent reporting when you get errors.

It also includes lots of nifty features for parameterized testing, fixtures, test configuration, mocking, etc...

If you are on a project that already uses unittest -- you still can run your tests with pytest, and get many of its advantages.