def test_percent_empty_value_handling(self):
        # Test empty deviation cases--should pass without error.
        with AcceptedPercent(0):  # <- Accepts empty deviations only.
            raise ValidationError([
                Invalid(None, 0),
                Invalid('', 0),
            ])

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

        diff = _getdiff(None, 0)                    # For None vs zero,
        self.assertEqual(diff, Deviation(None, 0))  # difference remains None.
示例#3
0
    def test_deviation(self):
        diff = Deviation(+1, 100)

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

        with self.assertRaises(AttributeError):
            diff.new_attribute = 202
示例#4
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)))

        diff = Deviation(float('nan'), 100)
        self.assertEqual(diff, eval(repr(diff)))
示例#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(float('nan'), 100)  # None reference.
        self.assertEqual(repr(diff), "Deviation(float('nan'), 100)")
示例#6
0
    def test_keywords(self):
        """Keywords should be passed to diff objet."""
        diff = _getdiff(5, 6, col1='AAA')
        self.assertEqual(diff, Deviation(-1, 6, col1='AAA'))

        diff = _getdiff('a', 6, col1='AAA')
        self.assertEqual(diff, Invalid('a', 6, col1='AAA'))

        diff = _getdiff(_NOTFOUND, 6, col1='AAA')
        self.assertEqual(diff, Deviation(-6, 6, col1='AAA'))
示例#7
0
    def test_repr(self):
        diff = Deviation(1, 100)  # Simple.
        self.assertEqual("Deviation(+1, 100)", repr(diff))

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

        diff = Deviation(3, 50, col1='a', col2='b')  # Using kwds.
        self.assertRegex(repr(diff), "Deviation\(\+3, 50, col1=u?'a', col2=u?'b'\)")

        diff = Deviation(1, None, col1='a')  # None reference.
        self.assertRegex(repr(diff), "Deviation\(\+1, None, col1=u?'a'\)")
    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)
    def test_multiarg_predicate(self):
        with self.assertRaises(ValidationError) as cm:

            def func(diff):
                return diff < 2

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

        remaining_diffs = cm.exception.differences
        self.assertEqual(list(remaining_diffs), [Deviation(+2, 5)])
示例#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 AcceptedArgs(function):  # <- Acceptance!
                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_is_common(self):
        """If requirement is common it should be omitted from Invalid
        difference (but not from Deviation differences).
        """
        diff = _getdiff('a', 6, is_common=True)
        self.assertEqual(diff, Invalid('a'))

        diff = _getdiff(_NOTFOUND, 6, is_common=True)
        self.assertEqual(diff, Deviation(-6, 6))
示例#14
0
    def test_notfound_comparisons(self):
        diff = _getdiff('a', _NOTFOUND)
        self.assertEqual(diff, Extra('a'))

        diff = _getdiff(_NOTFOUND, 'b')
        self.assertEqual(diff, Missing('b'))

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

        diff = _getdiff(0, _NOTFOUND)
        self.assertEqual(diff, Deviation(0, None))

        diff = _getdiff(_NOTFOUND, 6)
        self.assertEqual(diff, Deviation(-6, 6))  # <- Assymetric behavior
                                                  #    (see None vs numeric)!

        diff = _getdiff(_NOTFOUND, 0)
        self.assertEqual(diff, Deviation(None, 0))
示例#15
0
    def test_datetime_vs_datetime(self):
        diff = _make_difference(
            datetime.datetime(1989, 2, 24, hour=10, minute=30),
            datetime.datetime(1989, 2, 24, hour=11, minute=30),
        )

        self.assertEqual(
            diff,
            Deviation(
                datetime.timedelta(hours=-1),
                datetime.datetime(1989, 2, 24, hour=11, minute=30),
            ),
        )
示例#16
0
    def test_object_vs_object(self):
        """Non-numeric comparisons return Invalid type."""
        diff = _make_difference('a', 'b')
        self.assertEqual(diff, Invalid('a', 'b'))

        diff = _make_difference(5, 'b')
        self.assertEqual(diff, Invalid(5, 'b'))

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

        diff = _make_difference(float('nan'), 6)
        self.assertEqual(diff, Deviation(float('nan'), 6))

        diff = _make_difference(5, float('nan'))
        self.assertEqual(diff, Deviation(float('nan'), float('nan')))

        fn = lambda x: True
        diff = _make_difference('a', fn)
        self.assertEqual(diff, Invalid('a', fn))

        regex = re.compile('^test$')
        diff = _make_difference('a', regex)
        self.assertEqual(diff, Invalid('a', re.compile('^test$')))
示例#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_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)
示例#19
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)
示例#20
0
    def test_repr(self):
        diff = Deviation(1, 100)  # Simple.
        self.assertEqual("Deviation(+1, 100)", repr(diff))

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

        diff = Deviation(3, 50, col1='a', col2='b')  # Using kwds.
        self.assertRegex(repr(diff),
                         "Deviation\(\+3, 50, col1=u?'a', col2=u?'b'\)")

        with self.assertRaises(ValueError):
            diff = Deviation(0, 100)  # Zero diff.

        with self.assertRaises(ValueError):
            diff = Deviation(None, 100)  # None diff.

        diff = Deviation(1, None, col1='a')  # None reference.
        self.assertRegex(repr(diff), "Deviation\(\+1, None, col1=u?'a'\)")
示例#21
0
    def test_repr_eval(self):
        diff = Deviation(+1, 100)
        self.assertEqual(diff, eval(repr(diff)))  # Test __repr__ eval

        diff = Deviation(-1, 100, col4='foo', col5='bar')
        self.assertEqual(diff, eval(repr(diff)))  # Test __repr__ eval
示例#22
0
    def test_eq(self):
        diff1 = Deviation(1, 100)
        diff2 = Deviation(1, 100)
        self.assertEqual(diff1, diff2)

        diff1 = Deviation(1.0, 100.0)
        diff2 = Deviation(1.0, 100.0)
        self.assertEqual(diff1, diff2)

        diff1 = Deviation(1.0, 100)
        diff2 = Deviation(1, 100)
        self.assertEqual(diff1, diff2)

        diff1 = Deviation(1, 100.0)
        diff2 = Deviation(1, 100)
        self.assertEqual(diff1, diff2)

        diff1 = Deviation(1, 100, foo='aaa', bar='bbb')
        diff2 = Deviation(1, 100, bar='bbb', foo='aaa')
        self.assertEqual(diff1, diff2)

        diff1 = Deviation(1, 100)
        diff2 = Deviation(1, 250)
        self.assertNotEqual(diff1, diff2)

        diff1 = Deviation(+1, 100)
        diff2 = "Deviation(+1, 100)"
        self.assertNotEqual(diff1, diff2)
示例#23
0
 def test_hash(self):
     diff = Deviation(1, 100, col1='a', col2='b')
     self.assertIsInstance(hash(diff), int)
示例#24
0
 def test_str(self):
     diff = Deviation(5, 75, col1='a')
     self.assertEqual(str(diff), repr(diff))
示例#25
0
 def test_instantiation(self):
     Deviation(1, 100)  # Pass without error.
示例#26
0
    def test_zero_and_empty_value_handling(self):
        """Empty values receive special handling."""
        # Expected 0 (pass without error).
        Deviation(+5, 0)
        Deviation(-5, 0)
        Deviation(float('nan'), 0)
        with self.assertRaises(ValueError):
            Deviation(0, 0)

        # Expected numeric value (pass without error).
        Deviation(+1, 5)
        Deviation(-1, 5)
        Deviation(float('nan'), 5)

        # Expected non-zero, with empty or zero deviation.
        with self.assertRaises(ValueError):
            Deviation(0, 5)

        with self.assertRaises(TypeError):
            Deviation(None, 5)

        with self.assertRaises(TypeError):
            Deviation('', 5)

        with self.assertRaises(TypeError):
            Deviation(5, None)

        with self.assertRaises(TypeError):
            Deviation(5, '')

        # NaN handling.
        Deviation(float('nan'), 0)
        Deviation(0, float('nan'))
示例#27
0
 def test_numeric_vs_numeric(self):
     diff = _make_difference(5, 6)
     self.assertEqual(diff, Deviation(-1, 6))
示例#28
0
    def test_empty_value_handling(self):
        with self.assertRaises(ValueError):
            Deviation(0, 100)  # Zero diff.

        Deviation(0, None)
        Deviation(+5, None)
        Deviation(None, 0)
        with self.assertRaises(ValueError):
            Deviation(None, 5)  # Should be Deviation(-5, 5)

        Deviation(0, '')
        Deviation(+5, '')
        Deviation('', 0)
        with self.assertRaises(ValueError):
            Deviation('', 5)  # Should be Deviation(-5, 5)

        Deviation(0, float('nan'))
        Deviation(+5, float('nan'))
        Deviation(float('nan'), 0)
        with self.assertRaises(ValueError):
            Deviation(float('nan'), 5)  # Should be Deviation(-5, 5)

        with self.assertRaises(ValueError):
            Deviation(0, 1)  # Just no.

        # False is treated the same as zero.
        Deviation(+5, 0)
        Deviation(+5, False)

        with self.assertRaises(ValueError):
            Deviation(0, 0)

        with self.assertRaises(ValueError):
            Deviation(0, False)

        with self.assertRaises(ValueError):
            Deviation(False, 0)

        with self.assertRaises(ValueError):
            Deviation(False, 5)  # Should be Deviation(-5, 5)
示例#29
0
    def test_numeric_vs_none(self):
        diff = _getdiff(5, None)
        self.assertEqual(diff, Deviation(+5, None))

        diff = _getdiff(0, None)
        self.assertEqual(diff, Deviation(+0, None))
示例#30
0
 def test_numeric_vs_numeric(self):
     diff = _getdiff(5, 6)
     self.assertEqual(diff, Deviation(-1, 6))