How to test assert whether two lists of dictionaries (where a dict item contains a list) are the same

Micah Pearce :

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

Shubham Sharma :

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.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=297461&siteId=1