24

I'm writing a unit test for a function that returns a list of dictionaries. What is the best way to check if the output is as expected? Here, "as expected" means the dictionaries in the lists have the same keys and values, irrespective of the order of keys within the dictionary, or of the dictionary's order within the list. So something like this:

expect_output = [ {"c":4} , {"a" : 4 , "b" : 3}]
actual_ouput = [{"b" : 3, "a" : 4 }, {"c":4}]
# some function that would return true in this case.
Jad S
  • 2,705
  • 6
  • 29
  • 49

2 Answers2

25

If you are using unittest, there is a method for this:

self.assertItemsEqual(actual_output, expected_output)

In Python-3, this method is renamed to assertCountEqual

Jad S
  • 2,705
  • 6
  • 29
  • 49
chepner
  • 497,756
  • 71
  • 530
  • 681
  • 2
    This seems to work for Python2 but not for Python3 (I get an `AttributeError` and it says it can't find that assert function) – Jad S Jul 04 '16 at 13:57
  • I had not been aware that `assertItemsEqual` was removed from Python 3. See https://bugs.python.org/issue17866. – chepner Jul 04 '16 at 15:19
  • 1
    The docs you linked specify, albeit subtly, that it was renamed to `assertCountEqual` in Python 3 – Jad S Jul 04 '16 at 15:31
  • Any guidance on cases when the dictionaries themselves may contain dictionaries as values? This method gives `ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()` – Jake Stevens-Haas Oct 22 '19 at 09:13
  • 1
    Those aren't dictionaries; they're `numpy.array` values. The error message tells you what to do: you can't use an array as a truth value, because there are multiple ways to do so (is an array true if any value is true? if *all* values are true?). In any case, this should be a separate question which shows exactly what you are trying to test. (I assume an array comparison like `a == b` generates an array of boolean values based on an element-wise comparison, rather than a single boolean value.) – chepner Oct 22 '19 at 12:06
3

Here I've done a simple comparison between assertEqual and assertCountEqual as a value addition.

For assertEqual -> order of the list is important.

For assertCountEqual -> order of the list is not important.

def test_swapped_elements_1(self):
    self.assertEqual([{"b": 1}, {"a": 1, "b": 1}], [{"b": 1, "a": 1}, {"b": 1}])

def test_swapped_elements_2(self):
    self.assertCountEqual([{"b": 1}, {"a": 1, "b": 1}], [{"b": 1, "a": 1}, {"b": 1}])

def test_non_swapped_elements_1(self):
    self.assertEqual([{"a": 1, "b": 1}, {"b": 1}], [{"b": 1, "a": 1}, {"b": 1}])

def test_non_swapped_elements_2(self):
    self.assertCountEqual([{"a": 1, "b": 1}, {"b": 1}], [{"b": 1, "a": 1}, {"b": 1}])

Above results in:

PyCharm Screenshot

What failed one says: enter image description here

Therefore assertCountEqual should be used for OP's case.


This test was done in PyCharm latest version and Python 3.5

bhathiya-perera
  • 1,303
  • 14
  • 32