I'm creating my first test script (yay!) I'm have a list of dictionaries where one of the keys is a list. I'd like the test to past if the list (in the dictionary) is in any order. I know you can use assertCountEqual
to check list equality regardless of order, but can you do that for a list that contains a dictinary of lists? See below for example
Will Succeed
def test(self):
output = [2,1]
desired_output = [1,2]
self.assertCountEqual(output, desired_output)
Will Fail
def test(self):
desired_output = [{'count': 2, 'columns': ['col2', 'col5']}]
output = [{'count': 2, 'columns': ['col5', 'col2']}]
self.assertCountEqual(output, desired_output)
Thanks
The assertCountEqual(first, second, msg=None)
:
Test that sequence first contains the same elements as second, regardless of their order. When they don’t, an error message listing the differences between the sequences will be generated.
Important:
Calling assertCountEqual(first, second, msg=None)
is equivalent to callingassertEqual(Counter(list(first)), Counter(list(second)))
.
Note:
A Counter is a dict subclass for counting hashable objects. It is a collection where elements are stored as dictionary keys and their counts are stored as dictionary values.
For this to work the keys have to be hashable
but unfortunately the dict
is unhashable
because its mutable.
In order to perform the desired task you could use the frozenset
.
The frozenset
builds an immutable unordered collection of unique elements. In order to have the test succeed you will have to build a dict whose values corresponding to its keys are immutable. We can use the recursive approach to build a dictionary that contains immutable values.
Try this (UPDATE):
def getHashableDict(dictionary):
hashable_dict = {}
for key, value in dictionary.items():
if isinstance(value, list):
hashable_dict[key] = frozenset(value)
elif isinstance(value, dict):
hashable_dict[key] = getHashableDict(value)
else:
hashable_dict[key] = value
return frozenset(hashable_dict.items())
def test(self):
desired_output = [{'count': 2, 'columns': ['col2', 'col5']}]
output = [{'count': 2, 'columns': ['col5', 'col2']}]
output = [getHashableDict(item) for item in output] #--> create list of hashable types
desired_output = [getHashableDict(item) for item in desired_output]
self.assertCountEqual(output, desired_output)
The test will now succeed.