'As assert_result, but the order of objects is not considered.
The algorithm is very expensive but not a big deal for the small
numbers of rows that the test suite manipulates.'

def assert_unordered_result(self, result, cls, *expected):

    class immutabledict(dict, ):
        def __hash__(self):
            return id(self)
    found = util.IdentitySet(result)
    expected = set([immutabledict(e) for e in expected])
    for wrong in util.itertools_filterfalse((lambda o: (type(o) == cls)), found):
        fail(('Unexpected    type    "%s",    expected    "%s"' % (type(wrong).__name__, cls.__name__)))
    if (len(found) != len(expected)):
        fail(('Unexpected    object    count    "%s",    expected    "%s"' % (len(found), len(expected))))
    NOVALUE = object()
    def _compare_item(obj, spec):
        for (key, value) in spec.items():
            if isinstance(value, tuple):
                try:
                    self.assert_unordered_result(getattr(obj, key), value[0], *value[1])
                except AssertionError:
                    return False
            elif (getattr(obj, key, NOVALUE) != value):
                return False
        return True
    for expected_item in expected:
        for found_item in found:
            if _compare_item(found_item, expected_item):
                found.remove(found_item)
                break
        else:
            fail(('Expected    %s    instance    with    attributes    %s    not    found.' % (cls.__name__, repr(expected_item))))
    return True
