def test_compare_mixed_types(self): a = CompareDict({'aaa': 2, 'bbb': 3, 'ccc': 'z'}, 'foo') b = CompareDict({'aaa': 'y', 'bbb': 4.0, 'ccc': 5}, 'foo') expected = set([ xInvalid(2, 'y', foo='aaa'), xDeviation(-1, 4, foo='bbb'), xInvalid('z', 5, foo='ccc'), ]) self.assertEqual(expected, set(a.compare(b)))
def test_ne(self): data1 = {'a': 1, 'b': 2, 'c': 3, 'd': 4} a = CompareDict(data1, 'foo') b = CompareDict(data1, 'foo') self.assertFalse(a != b) data2 = {'a': 1, 'b': 2.5, 'c': 3, 'd': 4} a = CompareDict(data1, 'foo') b = CompareDict(data2, 'foo') self.assertTrue(a != b)
def test_repr(self): expected = "CompareDict({'a': 1}, key_names='foo')" result = CompareDict({'a': 1}, 'foo') self.assertEqual(expected, repr(result)) result = CompareDict({('a', ): 1}, ['foo']) # <- Single-item containers. self.assertEqual(expected, repr(result)) # Same "expected" as above. expected = "CompareDict({('a', 'b'): 1}, key_names=['foo', 'bar'])" result = CompareDict({('a', 'b'): 1}, ['foo', 'bar']) self.assertEqual(expected, repr(result))
def assertEqual(self, first, second, msg=None): """Fail if *first* does not satisfy *second* as determined by appropriate validation comparison. If *first* and *second* are comparable, a failure will raise a DataError containing the differences between the two. If the *second* argument is a helper-function (or other callable), it is used as a key which must return True for acceptable values. """ if not isinstance(first, BaseCompare): if isinstance(first, str) or not isinstance(first, Container): first = CompareSet([first]) elif isinstance(first, Set): first = CompareSet(first) elif isinstance(first, Mapping): first = CompareDict(first) if callable(second): equal = first.all(second) default_msg = 'first object contains invalid items' else: equal = first == second default_msg = 'first object does not match second object' if not equal: differences = first.compare(second) self.fail(msg or default_msg, differences)
def test_eq(self): data1 = {'a': 1, 'b': 2, 'c': 3, 'd': 4} a = CompareDict(data1, 'foo') b = CompareDict(data1, 'foo') self.assertTrue(a == b) data2 = {'a': 1, 'b': 2.5, 'c': 3, 'd': 4} a = CompareDict(data1, 'foo') b = CompareDict(data2, 'foo') self.assertFalse(a == b) # Test coersion of mapping. data1 = {'a': 1, 'b': 2, 'c': 3, 'd': 4} a = CompareDict(data1, 'foo') self.assertTrue(a == {'a': 1, 'b': 2, 'c': 3, 'd': 4}) # Test coersion of list of tuples. data1 = {'a': 1, 'b': 2, 'c': 3, 'd': 4} data2 = [ ('a', 1), # <- Should be coerced ('b', 2), # into CompareDict ('c', 3), # internally. ('d', 4) ] a = CompareDict(data1, 'foo') b = data2 self.assertTrue(a == b)
def test_init(self): data = {'a': 1, 'b': 2, 'c': 3, 'd': 4} x = CompareDict(data, 'foo') # dict. self.assertEqual(data, x) x = CompareDict(list(data.items()), 'foo') # list of tuples. self.assertEqual(data, x) # Non-mapping data (data error). data_list = ['a', 'b', 'c', 'd'] with self.assertRaises(ValueError): x = CompareDict(data_list, 'foo') # Single-item wrapped in collection. data = {('a', ): 1, ('b', ): 2, ('c', ): 3, ('d', ): 4} x = CompareDict(data, ['foo']) unwrapped = {'a': 1, 'b': 2, 'c': 3, 'd': 4} self.assertEqual(unwrapped, x) # Omitted *key_names*. data = {'a': 1, 'b': 2, 'c': 3, 'd': 4} x = CompareDict(data) self.assertEqual(data, x) self.assertEqual(x.key_names, ('_0', )) data = {('a', 'a'): 1, ('b', 'b'): 2, ('c', 'c'): 3} x = CompareDict(data) self.assertEqual(data, x) self.assertEqual(x.key_names, ('_0', '_1'))
def test_compare_function(self): a = CompareDict({'aaa': 'x', 'bbb': 'y', 'ccc': 'z'}, 'foo') # All True. result = a.compare(lambda x: len(x) == 1) self.assertEqual([], result) # Some False. result = a.compare(lambda a: a in ('x', 'y')) expected = [xInvalid('z', foo='ccc')] self.assertEqual(expected, result) # All True, multiple args. a = CompareDict({'aaa': (1, 2), 'bbb': (1, 3), 'ccc': (4, 8)}, 'foo') result = a.compare(lambda x, y: x < y) self.assertEqual([], result) # Some False, multiple args. a = CompareDict({'aaa': (1, 0), 'bbb': (1, 3), 'ccc': (3, 2)}, 'foo') result = a.compare(lambda x, y: x < y) expected = [xInvalid((1, 0), foo='aaa'), xInvalid((3, 2), foo='ccc')] self.assertEqual(expected, result)
def test_all_fn(self): # All True, single arg key function.. compare_obj = CompareDict({ 'aaa': (1, 2), 'bbb': (1, 3), 'ccc': (4, 8) }, 'foo') result = compare_obj.all(lambda x: x[0] < x[1]) self.assertTrue(result) # Some False, single arg key function.. compare_obj = CompareDict({ 'aaa': (1, 2), 'bbb': (5, 3), 'ccc': (4, 8) }, 'foo') result = compare_obj.all(lambda x: x[0] < x[1]) self.assertFalse(result) # All True, multi-arg key function. compare_obj = CompareDict({ 'aaa': (1, 2), 'bbb': (1, 3), 'ccc': (4, 8) }, 'foo') result = compare_obj.all(lambda x, y: x < y) self.assertTrue(result) # Some False,multi-arg key function. compare_obj = CompareDict({ 'aaa': (1, 2), 'bbb': (5, 3), 'ccc': (4, 8) }, 'foo') result = compare_obj.all(lambda x, y: x < y) self.assertFalse(result)
def test_compare_strings(self): a = CompareDict({'aaa': 'x', 'bbb': 'y', 'ccc': 'z'}, 'foo') b = CompareDict({'aaa': 'x', 'bbb': 'z', 'ccc': 'z'}, 'foo') expected = [xInvalid('y', 'z', foo='bbb')] self.assertEqual(expected, a.compare(b))
def test_compare_numbers(self): a = CompareDict({'aaa': 1, 'bbb': 2, 'ccc': 3, 'ddd': 4}, 'foo') b = CompareDict({'aaa': 1, 'bbb': 2, 'ccc': 3, 'ddd': 4}, 'foo') self.assertEqual([], a.compare(b), ('When there is no difference, ' 'compare should return an empty ' 'list.')) a = CompareDict({'aaa': 1, 'bbb': 2, 'ccc': 3, 'ddd': 4}, 'foo') b = CompareDict({'aaa': 1, 'bbb': 2.5, 'ccc': 3, 'ddd': 4}, 'foo') expected = [xDeviation(-0.5, 2.5, foo='bbb')] self.assertEqual(expected, a.compare(b)) # 'b' is zero in self/subject. a = CompareDict({'aaa': 1, 'bbb': 0, 'ccc': 3, 'ddd': 4}, 'foo') b = CompareDict({'aaa': 1, 'bbb': 2.5, 'ccc': 3, 'ddd': 4}, 'foo') expected = [xDeviation(-2.5, 2.5, foo='bbb')] self.assertEqual(expected, a.compare(b)) # 'bbb' is zero in other/reference. a = CompareDict({'aaa': 1, 'bbb': 2, 'ccc': 3, 'ddd': 4}, 'foo') b = CompareDict({'aaa': 1, 'bbb': 0, 'ccc': 3, 'ddd': 4}, 'foo') expected = [xDeviation(+2, 0, foo='bbb')] self.assertEqual(expected, a.compare(b)) # 'bbb' is missing from self/subject. a = CompareDict({'aaa': 1, 'ccc': 3, 'ddd': 4}, 'foo') b = CompareDict({'aaa': 1, 'bbb': 2.5, 'ccc': 3, 'ddd': 4}, 'foo') expected = [xDeviation(-2.5, 2.5, foo='bbb')] # <- QUESTION: This self.assertEqual(expected, a.compare(b)) # deviation looks the # same as 0 vs 2.5. # Is this OK? # 'bbb' is missing from a/subject. a = CompareDict({'aaa': 1, 'ccc': 3, 'ddd': 4}, 'foo') b = CompareDict({'aaa': 1, 'bbb': 0, 'ccc': 3, 'ddd': 4}, 'foo') expected = [xDeviation(None, 0, foo='bbb')] self.assertEqual(expected, a.compare(b)) # 'bbb' is empty string in a/subject. a = CompareDict({'aaa': 1, 'bbb': '', 'ccc': 3, 'ddd': 4}, 'foo') b = CompareDict({'aaa': 1, 'bbb': 0, 'ccc': 3, 'ddd': 4}, 'foo') expected = [xDeviation('', 0, foo='bbb')] self.assertEqual(expected, a.compare(b)) # 'bbb' is missing from b/reference. a = CompareDict({'aaa': 1, 'bbb': 0, 'ccc': 3, 'ddd': 4}, 'foo') b = CompareDict({'aaa': 1, 'ccc': 3, 'ddd': 4}, 'foo') expected = [xDeviation(0, None, foo='bbb')] self.assertEqual(expected, a.compare(b)) # Test coersion of *other*. a = CompareDict({'aaa': 1, 'bbb': 2, 'ccc': 3, 'ddd': 4}, 'foo') b = {'aaa': 1, 'bbb': 2.5, 'ccc': 3, 'ddd': 4} expected = [xDeviation(-0.5, 2.5, foo='bbb')] self.assertEqual(expected, a.compare(b))
def test_make_rows(self): make_set = lambda data: set(frozenset(row.items()) for row in data) # Single-item keys, single-item values. data = {'aaa': 1, 'bbb': 2, 'ccc': 3} result = CompareDict(data, 'foo') iterable = result.make_rows('bar') expected = [ { 'foo': 'aaa', 'bar': 1 }, { 'foo': 'bbb', 'bar': 2 }, { 'foo': 'ccc', 'bar': 3 }, ] self.assertEqual(make_set(expected), make_set(iterable)) # Composite keys. data = {('aaa', 'xxx'): 1, ('bbb', 'yyy'): 2, ('ccc', 'zzz'): 3} result = CompareDict(data, ['foo', 'bar']) iterable = result.make_rows('baz') expected = [ { 'foo': 'aaa', 'bar': 'xxx', 'baz': 1 }, { 'foo': 'bbb', 'bar': 'yyy', 'baz': 2 }, { 'foo': 'ccc', 'bar': 'zzz', 'baz': 3 }, ] self.assertEqual(make_set(expected), make_set(iterable)) # Composite values. data = {'aaa': ('xxx', 1), 'bbb': ('yyy', 2), 'ccc': ('zzz', 3)} result = CompareDict(data, 'foo') iterable = result.make_rows(['bar', 'baz']) expected = [ { 'foo': 'aaa', 'bar': 'xxx', 'baz': 1 }, { 'foo': 'bbb', 'bar': 'yyy', 'baz': 2 }, { 'foo': 'ccc', 'bar': 'zzz', 'baz': 3 }, ] self.assertEqual(make_set(expected), make_set(iterable)) data = {'aaa': 1, 'bbb': 2, 'ccc': 3} result = CompareDict(data, 'foo') with self.assertRaises(AssertionError): iterable = result.make_rows(['bar', 'baz']) # Too many *names*. data = {'aaa': (1, 2, 3), 'bbb': (2, 4, 6), 'ccc': (3, 6, 9)} result = CompareDict(data, 'foo') with self.assertRaises(AssertionError): iterable = result.make_rows('bar') # Too few *names*. data = {'aaa': 1, 'bbb': 2, 'ccc': 3} result = CompareDict(data, 'foo') with self.assertRaises(ValueError): iterable = result.make_rows( 'foo') # 'foo' conflicts with group_by.
def test_rebuild_comparedict(self): interface = [('col1', 'a'), ('col2', 'b'), ('col3', 'c'), (None, 'd')] adapted = AdapterSource(self.source, interface) rebuild_comparedict = adapted._rebuild_comparedict # Rebuild single key result as two key result. orig = CompareDict({'x': 1, 'y': 2, 'z': 3}, key_names='a') result = rebuild_comparedict(orig, 'c', 'c', 'a', ['a', 'b'], missing_col='') expected = CompareDict({ ('x', ''): 1, ('y', ''): 2, ('z', ''): 3 }, key_names=['a', 'b']) self.assertEqual(expected, result) # Rebuild two key result as three key result. orig = CompareDict({ ('x', 'x'): 1, ('y', 'y'): 2, ('z', 'z'): 3 }, key_names=['a', 'c']) result = rebuild_comparedict(orig, 'c', 'c', ['a', 'b'], ['a', 'd', 'b'], missing_col='') expected = CompareDict( { ('x', '', 'x'): 1, ('y', '', 'y'): 2, ('z', '', 'z'): 3 }, key_names=['a', 'd', 'b']) self.assertEqual(expected, result) # Rebuild single value tuple result as two value result. orig = CompareDict({'x': (1, ), 'y': (2, ), 'z': (3, )}, key_names='a') result = rebuild_comparedict(orig, 'c', ['c', 'd'], 'a', 'a', missing_col='') expected = CompareDict({ 'x': (1, ''), 'y': (2, ''), 'z': (3, '') }, key_names='a') self.assertEqual(expected, result) # Rebuild single value result as two value result. if True: orig = CompareDict({'x': 1, 'y': 2, 'z': 3}, key_names='a') result = rebuild_comparedict(orig, 'c', ['c', 'd'], 'a', 'a', missing_col='') expected = CompareDict({ 'x': (1, ''), 'y': (2, ''), 'z': (3, '') }, key_names=['c', 'd']) self.assertEqual(expected, result) # Rebuild two column result as three column result. orig = CompareDict({ 'x': (1, 2), 'y': (2, 4), 'z': (3, 6) }, key_names='a') result = rebuild_comparedict(orig, ['b', 'c'], ['b', 'd', 'c'], 'a', 'a', missing_col='empty') expected = CompareDict( { 'x': (1, 'empty', 2), 'y': (2, 'empty', 4), 'z': (3, 'empty', 6) }, key_names='a') self.assertEqual(expected, result) # Rebuild two key and two column result as three key and three column result. orig = CompareDict( { ('x', 'x'): (1, 2), ('y', 'y'): (2, 4), ('z', 'z'): (3, 6) }, key_names=['a', 'c']) result = rebuild_comparedict(orig, ['b', 'c'], ['b', 'd', 'c'], ['a', 'b'], ['a', 'd', 'b'], missing_col='empty') expected = CompareDict( { ('x', '', 'x'): (1, 'empty', 2), ('y', '', 'y'): (2, 'empty', 4), ('z', '', 'z'): (3, 'empty', 6) }, key_names=['a', 'd', 'b']) self.assertEqual(expected, result)