예제 #1
0
    def test_special_values(self):
        # Test empty deviation cases--should pass without error.
        with allowed_percent(0):  # <- Allows empty deviations only.
            raise ValidationError([
                Deviation(None, 0),
                Deviation('', 0),
            ])

        # Test diffs that can not be allowed as percentages.
        with self.assertRaises(ValidationError) as cm:
            with allowed_percent(2.00):  # <- Allows +/- 200%.
                raise ValidationError([
                    Deviation(None, 0),           # 0%
                    Deviation(0, None),           # 0%
                    Deviation(+2, 0),             # Can not be allowed by percent.
                    Deviation(+2, None),          # Can not be allowed by percent.
                    Deviation(float('nan'), 16),  # Not a number.
                ])
        actual = cm.exception.differences
        expected = [
            Deviation(+2, 0),             # Can not be allowed by percent.
            Deviation(+2, None),          # Can not be allowed by percent.
            Deviation(float('nan'), 16),  # Not a number.
        ]
        self.assertEqual(actual, expected)
예제 #2
0
    def test_none_vs_numeric(self):
        diff = _make_difference(None, 6)          # For None vs non-zero,
        self.assertEqual(diff, Deviation(-6, 6))  # difference is calculated
                                                  # as 0 - other.

        diff = _make_difference(None, 0)            # For None vs zero,
        self.assertEqual(diff, Deviation(None, 0))  # difference remains None.
예제 #3
0
    def test_some_differences(self):
        # Sequence order.
        data = {'a': ['x', 'y']}
        result = _apply_mapping_requirement(data, {'a': ['x', 'z']})
        result = dict(result)
        self.assertTrue(len(result) == 1)
        self.assertEqual(result, {'a': {(1, 2): [Invalid('y', 'z')]}})

        # Set membership.
        data = {'a': ['x', 'x'], 'b': ['x', 'y', 'z']}
        result = _apply_mapping_requirement(data, {
            'a': set(['x', 'y']),
            'b': set(['x', 'y'])
        })
        expected = {'a': [Missing('y')], 'b': [Extra('z')]}
        self.assertEqual(dict(result), expected)

        # Equality of single values.
        data = {'a': 'x', 'b': 10}
        result = _apply_mapping_requirement(data, {'a': 'j', 'b': 9})
        expected = {'a': Invalid('x', expected='j'), 'b': Deviation(+1, 9)}
        self.assertEqual(dict(result), expected)

        # Equality of multiple values.
        data = {'a': ['x', 'j'], 'b': [10, 9]}
        result = _apply_mapping_requirement(data, {'a': 'j', 'b': 9})
        expected = {'a': [Invalid('x')], 'b': [Deviation(+1, 9)]}
        self.assertEqual(dict(result), expected)

        # Equality of single tuples.
        data = {'a': (1, 'x'), 'b': (9, 10)}
        result = _apply_mapping_requirement(data, {'a': (1, 'j'), 'b': (9, 9)})
        expected = {
            'a': Invalid((1, 'x'), expected=(1, 'j')),
            'b': Invalid((9, 10), expected=(9, 9))
        }
        self.assertEqual(dict(result), expected)

        # Equality of multiple tuples.
        data = {'a': [(1, 'j'), (1, 'x')], 'b': [(9, 9), (9, 10)]}
        result = _apply_mapping_requirement(data, {'a': (1, 'j'), 'b': (9, 9)})
        expected = {'a': [Invalid((1, 'x'))], 'b': [Invalid((9, 10))]}
        self.assertEqual(dict(result), expected)

        # Equality of multiple values, missing key with single item.
        data = {'a': ['x', 'j'], 'b': [10, 9]}
        result = _apply_mapping_requirement(data, {'a': 'j', 'b': 9, 'c': 'z'})
        expected = {
            'a': [Invalid('x')],
            'b': [Deviation(+1, 9)],
            'c': Missing('z')
        }
        self.assertEqual(dict(result), expected)

        # Missing key, set membership.
        data = {'a': 'x'}
        result = _apply_mapping_requirement(data, {'a': 'x', 'b': set(['z'])})
        expected = {'b': [Missing('z')]}
        self.assertEqual(dict(result), expected)
예제 #4
0
    def test_deviation(self):
        diff = Deviation(+1, 100)

        with self.assertRaises(AttributeError):
            diff.expected = 101

        with self.assertRaises(AttributeError):
            diff.new_attribute = 202
예제 #5
0
    def test_repr(self):
        diff = Deviation(1, 100)  # Simple positive.
        self.assertEqual(repr(diff), "Deviation(+1, 100)")

        diff = Deviation(-1, 100)  # Simple negative.
        self.assertEqual(repr(diff), "Deviation(-1, 100)")

        diff = Deviation(1, None)  # None reference.
        self.assertEqual(repr(diff), "Deviation(+1, None)")
예제 #6
0
 def test_same_value_case(self):
     with self.assertRaises(ValidationError) as cm:
         with AcceptedPercent(0.25, 0.25):  # <- Accepts +25% only.
             raise ValidationError(self.differences)
     result_diffs = cm.exception.differences
     self.assertEqual({
         'aaa': Deviation(-1, 16),
         'ccc': Deviation(+2, 16)
     }, result_diffs)
예제 #7
0
 def test_same_value_case(self):
     with self.assertRaises(ValidationError) as cm:
         with AcceptedTolerance(4, 4):  # <- Accepts off-by-4 only.
             raise ValidationError(self.differences)
     result_diffs = cm.exception.differences
     self.assertEqual({
         'aaa': Deviation(-1, 16),
         'ccc': Deviation(+2, 16)
     }, result_diffs)
예제 #8
0
    def test_multiarg_predicate(self):
        with self.assertRaises(ValidationError) as cm:

            def func(diff):
                return diff < 2

            with allowed_args((func, 5)):
                raise ValidationError([
                    Deviation(+1, 5),
                    Deviation(+2, 5),
                ])

        remaining_diffs = cm.exception.differences
        self.assertEqual(list(remaining_diffs), [Deviation(+2, 5)])
예제 #9
0
    def test_percent_error(self):
        # Test "tolerance" syntax.
        with self.assertRaises(ValidationError) as cm:
            with AcceptedPercent(0.2):  # <- Accepts +/- 20%.
                raise ValidationError(self.differences)
        remaining = cm.exception.differences
        self.assertEqual(remaining, {'bbb': Deviation(+4, 16)})

        # Test "upper/lower" syntax.
        with self.assertRaises(ValidationError) as cm:
            with AcceptedPercent(0.0, 0.3):  # <- Accepts from 0 to 30%.
                raise ValidationError(self.differences)
        result_diffs = cm.exception.differences
        self.assertEqual({'aaa': Deviation(-1, 16)}, result_diffs)
예제 #10
0
    def test_function_predicate(self):
        with self.assertRaises(ValidationError) as cm:

            def function(args):
                diff, expected = args
                return diff < 2 and expected == 5

            with allowed_args(function):  # <- Allowance!
                raise ValidationError([
                    Deviation(+1, 5),
                    Deviation(+2, 5),
                ])

        remaining_diffs = cm.exception.differences
        self.assertEqual(list(remaining_diffs), [Deviation(+2, 5)])
예제 #11
0
    def test_interval_method(self):
        data = {'A': 5, 'B': 7, 'C': 9}
        validate.interval(data, 5, 10)

        data = [5, 7, 9]
        validate.interval(data, 5, 10)

        data = {'A': [7, 8, 9], 'B': [5, 6]}
        validate.interval(data, 5, 10)

        with self.assertRaises(ValidationError) as cm:
            data = {'A': 3, 'B': 6, 'C': [6, 7], 'D': [9, 10]}
            validate.interval(data, 5, 9)
        actual = cm.exception.differences
        expected = {'A': Deviation(-2, 5), 'D': [Deviation(+1, 9)]}
        self.assertEqual(actual, expected)
예제 #12
0
 def test_hashable(self):
     """Differences with hashable *args should be hashable."""
     # Following should all pass without error.
     hash(Missing('foo'))
     hash(Extra('bar'))
     hash(Invalid('baz'))
     hash(Invalid('baz', 'qux'))
     hash(Deviation(-1, 10))
예제 #13
0
    def test_some_false(self):
        data = ['x', 'x', 'y']
        result = _require_predicate_from_iterable(data, 'x')
        self.assertEqual(list(result), [Invalid('y')])

        data = [2, 2, 7]
        result = _require_predicate_from_iterable(data, 2)
        self.assertEqual(list(result), [Deviation(+5, 2)])
예제 #14
0
    def test_novalue_comparisons(self):
        diff = _make_difference('a', NOVALUE)
        self.assertEqual(diff, Extra('a'))

        diff = _make_difference(NOVALUE, 'b')
        self.assertEqual(diff, Missing('b'))

        # For numeric comparisons, NOVALUE behaves like None.
        diff = _make_difference(5, NOVALUE)
        self.assertEqual(diff, Deviation(+5, None))

        diff = _make_difference(0, NOVALUE)
        self.assertEqual(diff, Deviation(0, None))

        diff = _make_difference(NOVALUE, 6)
        self.assertEqual(diff, Deviation(-6, 6))  # <- Asymmetric behavior
                                                  #    (see None vs numeric)!

        diff = _make_difference(NOVALUE, 0)
        self.assertEqual(diff, Deviation(None, 0))
예제 #15
0
    def test_show_expected(self):
        """If requirement is common it should be omitted from Invalid
        difference (but not from Deviation differences).
        """
        diff = _make_difference('a', 6, show_expected=True)
        self.assertEqual(diff, Invalid('a', expected=6))

        diff = _make_difference('a', 6, show_expected=False)
        self.assertEqual(diff, Invalid('a'))

        diff = _make_difference(NOVALUE, 6, show_expected=False)
        self.assertEqual(diff, Deviation(-6, 6))
예제 #16
0
    def test_incompatible_diffs(self):
        """Test differences that cannot be fuzzy matched."""
        incompatible_diffs = [
            Missing('foo'),
            Extra('bar'),
            Invalid('baz'),  # <- Cannot accept if there's no expected value.
            Deviation(1, 10),
        ]
        differences = incompatible_diffs + self.differences

        with self.assertRaises(ValidationError) as cm:
            with AcceptedFuzzy(cutoff=0.5):
                raise ValidationError(differences)

        remaining = cm.exception.differences
        self.assertEqual(remaining, incompatible_diffs)
예제 #17
0
    def test_required_sequence(self):
        """When *required* is a sequence, should compare predicates by
        position.
        """
        with self.assertRaises(ValidationError) as cm:
            data = ['a', 2, 'x', 3]
            required = ['a', 2, 'c', 4]
            self.assertValid(data, required)

        error = cm.exception
        expected = [
            Invalid('x', expected='c'),
            Deviation(-1, 4),
        ]
        self.assertEqual(error.differences, expected)
        self.assertEqual(error.args[1], 'does not match required sequence')
예제 #18
0
    def test_approx_method(self):
        data = {'A': 5.00000001, 'B': 10.00000001}
        requirement = Query.from_object({'A': 5, 'B': 10})
        validate.approx(data, requirement)

        data = [5.00000001, 10.00000001]
        requirement = Query.from_object([5, 10])
        validate.approx(data, requirement)

        data = {'A': [5.00000001, 10.00000001], 'B': [5.00000001, 10.00000001]}
        requirement = Query.from_object({'A': [5, 10], 'B': [5, 10]})
        validate.approx(data, requirement)

        with self.assertRaises(ValidationError) as cm:
            data = {'A': 3, 'B': 10.00000001}
            requirement = {'A': 5, 'B': 10}
            validate.approx(data, requirement)
        actual = cm.exception.differences
        expected = {'A': Deviation(-2, 5)}
        self.assertEqual(actual, expected)
예제 #19
0
 def setUp(self):
     self.differences = {
         'aaa': Deviation(-1, 16),  # -6.25%
         'bbb': Deviation(+4, 16),  # 25.0%
         'ccc': Deviation(+2, 16),  # 12.5%
     }
예제 #20
0
 def test_NaN_values(self):
     with self.assertRaises(ValidationError):  # <- NaN values should not be caught!
         with allowed_deviation(0):
             raise ValidationError(Deviation(float('nan'), 0))
예제 #21
0
    def test_empty_string(self):
        with allowed_deviation(0):  # <- Pass without failure.
            raise ValidationError(Deviation('', 0))

        with allowed_deviation(0):  # <- Pass without failure.
            raise ValidationError(Deviation(0, ''))
예제 #22
0
 def test_same_value_case(self):
     with self.assertRaises(ValidationError) as cm:
         with allowed_deviation(3, 3):  # <- Allows off-by-3 only.
             raise ValidationError(self.differences)
     result_diffs = cm.exception.differences
     self.assertEqual({'aaa': Deviation(-1, 10), 'ccc': Deviation(+2, 10)}, result_diffs)
예제 #23
0
 def setUp(self):
     self.differences = {
         'aaa': Deviation(-1, 10),
         'bbb': Deviation(+3, 10),
         'ccc': Deviation(+2, 10),
     }
예제 #24
0
    def test_numeric_vs_none(self):
        diff = _make_difference(5, None)
        self.assertEqual(diff, Deviation(+5, None))

        diff = _make_difference(0, None)
        self.assertEqual(diff, Deviation(+0, None))
예제 #25
0
 def test_deviation(self):
     result = _require_predicate(11, 10, True)
     self.assertEqual(result, Deviation(+1, 10))
예제 #26
0
 def test_tolerance_syntax(self):
     with self.assertRaises(ValidationError) as cm:
         with allowed_percent(0.2):  # <- Allows +/- 20%.
             raise ValidationError(self.differences)
     remaining = cm.exception.differences
     self.assertEqual(remaining, {'bbb': Deviation(+4, 16)})
예제 #27
0
 def test_lower_upper_syntax(self):
     with self.assertRaises(ValidationError) as cm:
         with allowed_percent(0.0, 0.3):  # <- Allows from 0 to 30%.
             raise ValidationError(self.differences)
     result_diffs = cm.exception.differences
     self.assertEqual({'aaa': Deviation(-1, 16)}, result_diffs)
예제 #28
0
 def test_numeric_vs_numeric(self):
     diff = _make_difference(5, 6)
     self.assertEqual(diff, Deviation(-1, 6))
예제 #29
0
    def test_integration_examples(self):
        # Test allowance of +/- 2 OR +/- 6%.
        with self.assertRaises(ValidationError) as cm:
            differences = [
                Deviation(+2, 1),   # 200%
                Deviation(+4, 8),   #  50%
                Deviation(+8, 32),  #  25%
            ]
            with allowed_deviation(2) | allowed_percent(0.25):
                raise ValidationError(differences)

        remaining = cm.exception.differences
        self.assertEqual(remaining, [Deviation(+4, 8)])

        # Test missing-type AND matching-value.
        with self.assertRaises(ValidationError) as cm:
            differences = [
                Missing('A'),
                Missing('B'),
                Extra('C'),
            ]
            with allowed_missing() & allowed_args(lambda x: x == 'A'):
                raise ValidationError(differences)

        remaining = cm.exception.differences
        self.assertEqual(remaining, [Missing('B'), Extra('C')])

        # Test missing-type OR allowed-limit.
        with self.assertRaises(ValidationError) as cm:
            differences = [
                Extra('A'),
                Missing('B'),
                Extra('C'),
                Missing('D'),
            ]
            with allowed_limit(1) | allowed_missing():
                raise ValidationError(differences)

        remaining = cm.exception.differences
        self.assertEqual(remaining, [Extra('C')])

        # Test missing-type AND allowed-limit.
        with self.assertRaises(ValidationError) as cm:
            differences = [
                Extra('A'),
                Missing('B'),
                Missing('C'),
            ]
            with allowed_limit(1) & allowed_missing():  # Allows only 1 missing.
                raise ValidationError(differences)

        remaining = cm.exception.differences
        self.assertEqual(remaining, [Extra('A'), Missing('C')])

        # Test missing-type OR allowed-limit.
        with self.assertRaises(ValidationError) as cm:
            differences = [
                Extra('A'),
                Missing('B'),
                Extra('C'),
                Missing('D'),
            ]
            with allowed_limit(1) | allowed_specific(Extra('A')):
                raise ValidationError(differences)

        remaining = cm.exception.differences
        self.assertEqual(remaining, [Extra('C'), Missing('D')])
예제 #30
0
    def test_repr_eval(self):
        diff = Deviation(+1, 100)
        self.assertEqual(diff, eval(repr(diff)))

        diff = Deviation(-1, 100)
        self.assertEqual(diff, eval(repr(diff)))