From a12e7205141c5a0c29b370eaf3a430344d01287b Mon Sep 17 00:00:00 2001 From: Julian Edwards Date: Sat, 28 Mar 2026 14:17:00 +1000 Subject: [PATCH] Add LessThanOrEqual + GreaterThanOrEqual matchers Fixes issue https://github.com/testing-cabal/testtools/issues/594 --- tests/matchers/test_basic.py | 32 ++++++++++++++++++++++++++++++++ testtools/matchers/__init__.py | 4 ++++ testtools/matchers/_basic.py | 16 ++++++++++++++++ 3 files changed, 52 insertions(+) diff --git a/tests/matchers/test_basic.py b/tests/matchers/test_basic.py index 9fa5f9fe..32dc6cd6 100644 --- a/tests/matchers/test_basic.py +++ b/tests/matchers/test_basic.py @@ -12,10 +12,12 @@ EndsWith, Equals, GreaterThan, + GreaterThanOrEqual, HasLength, Is, IsInstance, LessThan, + LessThanOrEqual, MatchesRegex, Nearly, NotEquals, @@ -217,6 +219,36 @@ class TestGreaterThanInterface(TestCase, TestMatchersInterface): ] +class TestLessThanOrEqualInterface(TestCase, TestMatchersInterface): + matches_matcher: ClassVar[Matcher[Any]] = LessThanOrEqual(4) + matches_matches: ClassVar[list[Any]] = [-5, 3, 4] + matches_mismatches: ClassVar[list[Any]] = [5, 5000] + + str_examples: ClassVar = [ + ("LessThanOrEqual(12)", LessThanOrEqual(12)), + ] + + describe_examples: ClassVar = [ + ("5 > 4", 5, LessThanOrEqual(4)), + ("6 > 4", 6, LessThanOrEqual(4)), + ] + + +class TestGreaterThanOrEqualInterface(TestCase, TestMatchersInterface): + matches_matcher: ClassVar[Matcher[Any]] = GreaterThanOrEqual(4) + matches_matches: ClassVar[list[Any]] = [4, 5, 8] + matches_mismatches: ClassVar[list[Any]] = [-2, 0, 3] + + str_examples: ClassVar = [ + ("GreaterThanOrEqual(12)", GreaterThanOrEqual(12)), + ] + + describe_examples: ClassVar = [ + ("3 < 4", 3, GreaterThanOrEqual(4)), + ("2 < 4", 2, GreaterThanOrEqual(4)), + ] + + class TestContainsInterface(TestCase, TestMatchersInterface): matches_matcher: ClassVar[Matcher[Any]] = Contains("foo") matches_matches: ClassVar[list[Any]] = ["foo", "afoo", "fooa"] diff --git a/testtools/matchers/__init__.py b/testtools/matchers/__init__.py index 1a4fa55e..96f95429 100644 --- a/testtools/matchers/__init__.py +++ b/testtools/matchers/__init__.py @@ -30,6 +30,7 @@ "FileContains", "FileExists", "GreaterThan", + "GreaterThanOrEqual", "HasLength", "HasPermissions", "Is", @@ -37,6 +38,7 @@ "IsInstance", "KeysEqual", "LessThan", + "LessThanOrEqual", "MatchesAll", "MatchesAny", "MatchesDict", @@ -67,10 +69,12 @@ EndsWith, Equals, GreaterThan, + GreaterThanOrEqual, HasLength, Is, IsInstance, LessThan, + LessThanOrEqual, MatchesRegex, Nearly, NotEquals, diff --git a/testtools/matchers/_basic.py b/testtools/matchers/_basic.py index cf1b5e93..afea4bfb 100644 --- a/testtools/matchers/_basic.py +++ b/testtools/matchers/_basic.py @@ -5,10 +5,12 @@ "EndsWith", "Equals", "GreaterThan", + "GreaterThanOrEqual", "HasLength", "Is", "IsInstance", "LessThan", + "LessThanOrEqual", "MatchesRegex", "Nearly", "NotEquals", @@ -200,6 +202,20 @@ class GreaterThan(_BinaryComparison[T]): mismatch_string = "<=" +class LessThanOrEqual(_BinaryComparison[T]): + """Matches if the item is less than or equal to the matchers reference object.""" + + comparator = operator.le + mismatch_string = ">" + + +class GreaterThanOrEqual(_BinaryComparison[T]): + """Matches if the item is greater than or equal to the matchers reference object.""" + + comparator = operator.ge + mismatch_string = "<" + + class _NotNearlyEqual(Mismatch, Generic[T]): """Mismatch for Nearly matcher."""