@@ -0,0 +1,1543 @@
+__author__ = 'ibakepunk'%0A%0A%0Adef get_diff(expected, actual, key=None):%0A    %22%22%22%0A    Recursively gets xpath of elements that differ.%0A    :param expected: Expected dict%0A    :param actual: Actual dict%0A    :type expected: dict%0A    :type actual: dict%0A    :return: Diff string%0A    :rtype: str%0A    %22%22%22%0A    diff = ''%0A    key = key or '/'%0A    if isinstance(expected, dict) and isinstance(actual, dict):%0A        d1_not_d2 = %5Bk for k in expected if k not in actual%5D%0A        d2_not_d1 = %5Bk for k in actual if k not in expected%5D%0A        diff += 'Expected keys at %7Bkey%7D not found: %7Bkeys%7D'.format(key=key, keys=str(d1_not_d2) + '%5Cn') if d1_not_d2 %5C%0A            else ''%0A        diff += 'Not expected keys at %7Bkey%7D found: %7Bkeys%7D'.format(key=key, keys=str(d2_not_d1) + '%5Cn') if d2_not_d1 %5C%0A            else ''%0A        for k in expected:%0A            if k in actual:%0A                diff += get_diff(expected%5Bk%5D, actual%5Bk%5D, key + '/' + k)%0A    elif isinstance(expected, list) and isinstance(actual, list):%0A        if len(expected) != len(actual):%0A            diff += '%7Bkey%7D expected length %7Bexp_len%7D, got %7Bact_len%7D%5Cn'.format(key=key, exp_len=len(expected),%0A                                                                              act_len=len(actual))%0A            return diff%0A        for i, (v1, v2) in enumerate(zip(expected, actual)):%0A            diff += get_diff(v1, v2, key + '%5B' + str(i) + '%5D')%0A    else:%0A        if expected != actual:%0A            diff += '%7Bkey%7D must be %7Bexp%7D, got %7Bact%7D%5Cn'.format(key=key, exp=str(expected), act=str(actual))%0A    return diff

Add differ itself