def test_dict_v_dict_membership_fail(self): with self.assertRaises(DataError) as cm: first = {'foo': 'AAA', 'bar': 'BBB'} second = {'foo': 'AAA', 'bar': 'BBB', 'baz': 'CCC'} self.assertEqual(first, second) differences = cm.exception.differences super(DataTestCase, self).assertEqual(differences, [Missing('CCC', _0='baz')])
def test_keys_nonmapping(self): # Missing required keyword 'diffs'. in_diffs = [Missing('foo'), Missing('bar')] function = lambda first, second: first == 'AAA' regex = "accepts only 'diffs' keyword, found 'keys'" with self.assertRaisesRegex(ValueError, regex): with allow_any(keys=function): # <- expects 'diffs='. raise DataError('example error', in_diffs) # Disallowed keywords ('keys'). in_diffs = [Missing('foo'), Missing('bar')] function = lambda first, second: first == 'AAA' with self.assertRaisesRegex(ValueError, "found 'keys'"): with allow_any(diffs=function, keys=function): # <- 'keys=' not allowed. raise DataError('example error', in_diffs)
def test_allow_some(self): differences = [Extra('xxx'), Missing('yyy')] with self.assertRaises(DataError) as cm: with allow_limit(1): # <- Allows only 1 but there are 2! raise DataError('example error', differences) rejected = list(cm.exception.differences) self.assertEqual(differences, rejected)
def test_allow_some(self): differences = [Extra('xxx'), Missing('yyy')] with self.assertRaises(DataError) as cm: with allow_missing(): raise DataError('example error', differences) rejected = list(cm.exception.differences) self.assertEqual(rejected, [Extra('xxx')])
def test_dict_of_diffs_exceeds(self): differences = {'foo': Extra('xxx'), 'bar': Missing('yyy')} with self.assertRaises(DataError) as cm: with allow_limit(1): # <- Allows only 1 but there are 2! raise DataError('example error', differences) rejected = cm.exception.differences self.assertEqual(differences, rejected)
def test_required_set(self): """When *required* is a set, _compare_set() should be called.""" with self.assertRaises(DataError) as cm: required = set([1, 2, 4]) data = set([1, 2, 3]) self.assertValid(data, required) differences = cm.exception.differences self.assertEqual(set(differences), set([Extra(3), Missing(4)]))
def test_add_mandatory_message(self): testresult = DataTestResult() err_tuple = (ValidationError, ValidationError([Missing('x')], 'example failure'), '<dummy traceback>') new_tuple = testresult._add_mandatory_message(err_tuple) _, err, _ = new_tuple self.assertRegex(str(err), 'mandatory test failed, stopping early')
def test_state_labels(detail, summary): data = detail({'state/territory'}) requirement = summary({'state/territory'}) omitted_territory = accepted([ Missing('Jervis Bay Territory'), ]) with omitted_territory: validate(data, requirement)
def test_dict_input(self): # Flat dictionary input. generator = _walk_diff({'key1': Missing('val1'), 'key2': Missing('val2')}) self.assertEqual(set(generator), set([Missing('val1'), Missing('val2')])) # Nested dictionary input. generator = _walk_diff({'key1': Missing('val1'), 'key2': {'key3': Missing('baz')}}) self.assertEqual(set(generator), set([Missing('val1'), Missing('baz')]))
def test_required_mapping(self): """When *required* is a mapping, _compare_mapping() should be called.""" with self.assertRaises(DataError) as cm: required = {'AAA': 'a', 'BBB': 'b', 'CCC': 'c'} data = {'AAA': 'a', 'BBB': 'b', 'DDD': 'd'} self.assertValid(data, required) differences = cm.exception.differences self.assertEqual(differences, {'CCC': Missing('c'), 'DDD': Extra('d')})
def test_mapping_none_allowed(self): differences = {'foo': Extra('xxx'), 'bar': Missing('yyy')} allowed = {} with self.assertRaises(DataError) as cm: with allow_only(allowed): raise DataError('example error', differences) actual = cm.exception.differences self.assertEqual(differences, actual)
def test_list_input(self): # Flat. generator = _walk_diff([Missing('val1'), Missing('val2')]) self.assertEqual(list(generator), [Missing('val1'), Missing('val2')]) # Nested. generator = _walk_diff([Missing('val1'), [Missing('val2')]]) self.assertEqual(list(generator), [Missing('val1'), Missing('val2')])
def test_missing(self): data = [('label1', ), ('a', ), ('b', )] self.subject = MinimalSource(data) with self.assertRaises(DataError) as cm: required_set = set(['label1', 'value']) self.assertSubjectColumns(required=required_set) # <- test assert differences = cm.exception.differences self.assertEqual(set(differences), set([Missing('value')]))
def test_keys_keyword(self): in_diffs = { 'foo': Extra('xxx'), 'bar': Extra('yyy'), 'baz': Missing('zzz'), } with self.assertRaises(DataError) as cm: def additional_helper(x): return x in ('foo', 'baz') with allow_extra(keys=additional_helper): raise DataError('example error', in_diffs) rejected = cm.exception.differences self.assertEqual(rejected, { 'bar': Extra('yyy'), 'baz': Missing('zzz') })
def test_state_labels(self): data = detail({'state/territory'}) requirement = summary({'state/territory'}) omitted_territory = self.acceptedSpecific([ Missing('Jervis Bay Territory'), ]) with omitted_territory: self.assertValid(data, requirement)
def test_mapping_some_good(self): """Given a mapping in which all items are valid, *function* should omit all items and simply return an empty mapping. """ def function(mapping): for key, diff in mapping.items(): if diff.value == 'bar': yield (key, diff) in_diffs = { ('AAA', 'xxx'): Missing('foo'), ('BBB', 'yyy'): Missing('bar') } with self.assertRaises(DataError) as cm: with allow_iter(function): raise DataError('example error', in_diffs) out_diffs = cm.exception.differences self.assertEqual(out_diffs, {('BBB', 'yyy'): Missing('bar')})
def test_mapping_mismatched_types(self): # Dict of diffs vs list of allowed. differences = {'foo': Extra('xxx'), 'bar': Missing('yyy')} allowed = [Extra('xxx'), Missing('yyy')] regex = ("expects non-mapping differences but found 'dict' of " "differences") with self.assertRaisesRegex(ValueError, regex): with allow_only(allowed): raise DataError('example error', differences) # List of diffs vs dict of allowed. differences = [Extra('xxx'), Missing('yyy')] allowed = {'foo': Extra('xxx'), 'bar': Missing('yyy')} regex = ("expects mapping of differences but found 'list' of " "differences") with self.assertRaisesRegex(ValueError, regex): with allow_only(allowed): raise DataError('example error', differences)
def test_kwds_exceeds_limit(self): differences = [Extra('xxx'), Missing('yyy'), Extra('zzz')] with self.assertRaises(DataError) as cm: is_extra = lambda x: isinstance(x, Extra) with allow_limit(1, diffs=is_extra): # <- Limit of 1 and is_extra(). raise DataError('example error', differences) rejected = list(cm.exception.differences) self.assertEqual(differences, rejected)
def test_method(_self): first = set([1, 2, 3]) second = set([1, 2, 3, 4]) with self.assertRaises(DataError) as cm: _self.assertEqual(first, second) # <- Wrapped method! msg = 'In 0.7.0, assertEqual() should raise DataError.' _self.assertTrue(isinstance(cm.exception, DataError), msg) diffs = list(cm.exception.differences) _self.assertEqual(diffs, [Missing(4)])
def test_kwds(self): diff_set = set([ Missing('xxx', aaa='foo'), Missing('yyy', aaa='bar'), Extra('zzz', aaa='foo'), ]) with self.assertRaises(DataError) as cm: # Allows 2 with aaa='foo' and there are two (only aaa='bar' is rejected). with allow_limit(2, 'example message', aaa='foo'): raise DataError('example error', diff_set) rejected = set(cm.exception.differences) self.assertEqual(rejected, set([Missing('yyy', aaa='bar')])) with self.assertRaises(DataError) as cm: # Allows 1 with aaa='foo' but there are 2 (all are rejected)! with allow_limit(1, 'example message', aaa='foo'): raise DataError('example error', diff_set) rejected = set(cm.exception.differences) self.assertEqual(rejected, diff_set)
def test_kwds(self): in_diffs = [ Extra('xxx', aaa='foo'), Extra('yyy', aaa='bar'), Missing('zzz', aaa='foo'), ] with self.assertRaises(DataError) as cm: with allow_any('example message', aaa='foo'): raise DataError('example error', in_diffs) rejected = list(cm.exception.differences) self.assertEqual(rejected, [Extra('yyy', aaa='bar')])
def test_keys_mapping(self): # Function accepts single argument. in_diffs = {'AAA': Missing('foo'), 'BBB': Missing('bar')} function = lambda x: x == 'AAA' with self.assertRaises(DataError) as cm: with allow_any(keys=function): raise DataError('example error', in_diffs) rejected = cm.exception.differences self.assertEqual(rejected, {'BBB': Missing('bar')}) # Function accepts multiple arguments. in_diffs = { ('AAA', 'XXX'): Missing('foo'), ('BBB', 'YYY'): Missing('bar') } def function(first, second): # <- Multiple args. return second == 'XXX' with self.assertRaises(DataError) as cm: with allow_any(keys=function): raise DataError('example error', in_diffs) rejected = cm.exception.differences self.assertEqual(rejected, {('BBB', 'YYY'): Missing('bar')})
def test_returns_bad_sequence(self): """In place of mapping objects, *function* may instead return an iterable of two-item sequences but if the sequence contains more or less items, a ValueError should be raised. """ in_diffs = { ('AAA', 'xxx'): Missing('foo'), ('BBB', 'yyy'): Missing('bar') } # mapping / iterable of 1-item sequences. return_val = [ [Missing('foo')], # <- One item. [Missing('bar')] ] # <- One item. regex = ('has length 1.*2 is required') with self.assertRaisesRegex(ValueError, regex): # <- ValueError! with allow_iter(lambda x: return_val): raise DataError('example error', in_diffs) # mapping / iterable of 3-item sequences. return_val = [ [('AAA', 'xxx'), Missing('foo'), None], # <- Three items. [('BBB', 'yyy'), Missing('bar'), None] ] # <- Three items. regex = 'has length 3.*2 is required' with self.assertRaisesRegex(ValueError, regex): # <- ValueError! with allow_iter(lambda x: return_val): raise DataError('example error', in_diffs)
def test_items_mapping(self): # Function of one argument. in_diffs = {'AAA': Missing('foo'), 'BBB': Missing('bar')} def function(item): key, diff = item # Unpack item tuple. return key == 'AAA' with self.assertRaises(DataError) as cm: with allow_any(items=function): raise DataError('example error', in_diffs) rejected = cm.exception.differences self.assertEqual(rejected, {'BBB': Missing('bar')}) # Function of two arguments. in_diffs = {'AAA': Missing('foo'), 'BBB': Missing('bar')} def function(key, diff): return key == 'AAA' with self.assertRaises(DataError) as cm: with allow_any(items=function): raise DataError('example error', in_diffs) rejected = cm.exception.differences self.assertEqual(rejected, {'BBB': Missing('bar')}) # Function of three arguments. in_diffs = { ('AAA', 'XXX'): Missing('foo'), ('BBB', 'YYY'): Missing('bar') } def function(key1, key2, diff): return key2 == 'XXX' with self.assertRaises(DataError) as cm: with allow_any(items=function): raise DataError('example error', in_diffs) rejected = cm.exception.differences self.assertEqual(rejected, {('BBB', 'YYY'): Missing('bar')})
def test_mapping(self): required = {'AAA': 'a', 'BBB': 'b', 'CCC': 'c'} data = {'AAA': 'a', 'BBB': 'b', 'CCC': 'c'} result = _compare_mapping(data, required) self.assertEqual(result, {}) data = {'AAA': 'a', 'BBB': 'b', 'CCC': 'c', 'DDD': '3'} result = _compare_mapping(data, required) self.assertEqual(result, {'DDD': Extra('3')}) data = {'AAA': 'a', 'CCC': 'c', 'DDD': '3'} result = _compare_mapping(data, required) self.assertEqual(result, {'BBB': Missing('b'), 'DDD': Extra('3')})
def test_nondiff_items(self): # Flat list. with self.assertRaises(TypeError): generator = _walk_diff(['val1', 'val2']) list(generator) # Flat dict. with self.assertRaises(TypeError): generator = _walk_diff({'key1': 'val1', 'key2': 'val2'}) list(generator) # Nested list. with self.assertRaises(TypeError): generator = _walk_diff([Missing('val1'), ['val2']]) list(generator) # Nested collection of dict, list, and unwrapped items. with self.assertRaises(TypeError): generator = _walk_diff({'key1': Missing('val1'), 'key2': [Missing('val2'), [Missing('val3'), 'val4']]}) list(generator)
def test_keyword_combinations(self): in_diffs = { ('AAA', 'XXX'): Missing('foo'), ('BBB', 'YYY'): Missing('foo'), ('CCC', 'XXX'): Extra('bar'), ('DDD', 'XXX'): Missing('foo') } def fn1(key1, key2): return key2 == 'XXX' def fn2(diff): return diff.value == 'foo' with self.assertRaises(DataError) as cm: with allow_any(keys=fn1, diffs=fn2): raise DataError('example error', in_diffs) rejected = cm.exception.differences self.assertEqual(rejected, { ('BBB', 'YYY'): Missing('foo'), ('CCC', 'XXX'): Extra('bar') })
def test_iterable(self): required = set(['a', 'b', 'c']) data = iter(['a', 'b', 'c']) result = _compare_set(data, required) self.assertEqual(result, []) data = iter(['a', 'b', 'c', '3']) result = _compare_set(data, required) self.assertEqual(result, [Extra('3')]) data = iter(['a', 'c', '3']) result = _compare_set(data, required) result = set(result) self.assertEqual(result, set([Missing('b'), Extra('3')]))
def test_mapping(self): required = set(['a', 'b', 'c']) data = {'AAA': 'a', 'BBB': 'b', 'CCC': 'c'} result = _compare_set(data, required) self.assertEqual(result, []) data = {'AAA': 'a', 'BBB': 'b', 'CCC': 'c', 'DDD': '3'} result = _compare_set(data, required) self.assertEqual(result, [Extra('3')]) data = {'AAA': 'a', 'CCC': 'c', 'DDD': '3'} result = _compare_set(data, required) result = set(result) self.assertEqual(result, set([Missing('b'), Extra('3')]))
def test_missing(self): ref = [ ('label1', 'label2'), ('a', 'x'), ('b', 'y'), ('c', 'z'), ('d', '#'), # <- Reference has one additional item. ] self.reference = MinimalSource(ref) with self.assertRaises(DataError) as cm: self.assertSubjectSet('label1') differences = cm.exception.differences self.assertEqual(differences, [Missing('d')])