Skip to content

Commit

Permalink
constructor level type checks + tests (#303)
Browse files Browse the repository at this point in the history
Summary:
<!--
Thank you for your interest in this project. Bugs filed and PRs submitted are appreciated!

Please make sure that you are familiar with and follow the Code of Conduct of this project which can be found at https://github.com/facebookincubator/TestSlide/blob/master/CODE_OF_CONDUCT.md

Also, please make sure you're familiar with and follow the instructions in the contributing guidelines which can  be found at https://github.com/facebookincubator/TestSlide/blob/master/CONTRIBUTING.md

-->

**What:**

Fix for issue #233
1. Added Constructor level input type checks for various Matchers.

**Why:**

**How:**

_For point 1_
Checked for the passed arguments to be of the specified types. If not, raised a `ValueError` with appropriate error message.

**Risks:**

N/A. At least not intentionally.

**Checklist**:

<!--
Have you done all of these things?
To check an item, place an "x" in the box like so: "- [x] Tests"
Add "N/A" to the end of each line that's irrelevant to your changes
-->

- [x] Added tests, if you've added code that should be tested
- [x] Updated the documentation, if you've changed APIs
- [x] Ensured the test suite passes
- [x] Made sure your code lints
- [x] Completed the Contributor License Agreement ("CLA")

Pull Request resolved: #303

Reviewed By: doranand

Differential Revision: D28693338

Pulled By: deathowl

fbshipit-source-id: 91cbba5951e5e7a7ed65515756587be2bbf78f54
  • Loading branch information
EricLiclair authored and facebook-github-bot committed May 26, 2021
1 parent b70d59b commit aa4a514
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 1 deletion.
66 changes: 66 additions & 0 deletions tests/matchers_unittest.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,75 +18,111 @@ def test_NotThisInt(self):
self.assertEqual(testslide.matchers.NotThisInt(666), 42)
self.assertNotEqual(testslide.matchers.NotThisInt(69), 69)
self.assertNotEqual(testslide.matchers.NotThisInt(42), "derp")
with self.assertRaises(ValueError):
testslide.matchers.NotThisInt("derp")
with self.assertRaises(ValueError):
testslide.matchers.NotThisInt(1.340)

def test_IntBetween(self):
self.assertEqual(testslide.matchers.IntBetween(21, 666), 42)
self.assertEqual(testslide.matchers.IntBetween(21, 666), 21)
self.assertEqual(testslide.matchers.IntBetween(21, 666), 666)
self.assertNotEqual(testslide.matchers.IntBetween(42, 69), 666)
self.assertNotEqual(testslide.matchers.IntBetween(42, 69), "derp")
with self.assertRaises(ValueError):
testslide.matchers.IntBetween("derp", 42)
with self.assertRaises(ValueError):
testslide.matchers.IntBetween(42.42, "derp")
with self.assertRaises(ValueError):
testslide.matchers.IntBetween("derp", "derp")

def test_IntGreaterThan(self):
self.assertEqual(testslide.matchers.IntGreaterThan(21), 42)
self.assertNotEqual(testslide.matchers.IntGreaterThan(21), 21)
self.assertNotEqual(testslide.matchers.IntGreaterThan(21), 20)
self.assertNotEqual(testslide.matchers.IntGreaterThan(42), "derp")
with self.assertRaises(ValueError):
testslide.matchers.IntGreaterThan("derp")

def test_IntGreaterOrEquals(self):
self.assertEqual(testslide.matchers.IntGreaterOrEquals(21), 42)
self.assertEqual(testslide.matchers.IntGreaterOrEquals(21), 21)
self.assertNotEqual(testslide.matchers.IntGreaterOrEquals(21), 20)
self.assertNotEqual(testslide.matchers.IntGreaterOrEquals(42), "derp")
with self.assertRaises(ValueError):
testslide.matchers.IntGreaterOrEquals("derp")

def test_IntLessThan(self):
self.assertEqual(testslide.matchers.IntLessThan(21), 20)
self.assertNotEqual(testslide.matchers.IntLessThan(21), 21)
self.assertNotEqual(testslide.matchers.IntLessThan(21), 22)
self.assertNotEqual(testslide.matchers.IntLessThan(42), "derp")
with self.assertRaises(ValueError):
testslide.matchers.IntLessThan("derp")

def test_IntLessOrEquals(self):
self.assertEqual(testslide.matchers.IntLessOrEquals(21), 20)
self.assertEqual(testslide.matchers.IntLessOrEquals(21), 21)
self.assertNotEqual(testslide.matchers.IntLessOrEquals(21), 22)
self.assertNotEqual(testslide.matchers.IntLessOrEquals(42), "derp")
with self.assertRaises(ValueError):
testslide.matchers.IntLessOrEquals("derp")


class FloatMatcherTest(testslide.TestCase):
def test_NotThisFloat(self):
self.assertEqual(testslide.matchers.NotThisFloat(66.6), 4.2)
self.assertNotEqual(testslide.matchers.NotThisFloat(6.9), 6.9)
self.assertNotEqual(testslide.matchers.NotThisFloat(4.2), "derp")
with self.assertRaises(ValueError):
testslide.matchers.NotThisFloat("derp")
with self.assertRaises(ValueError):
testslide.matchers.NotThisFloat(10)

def test_FloatBetween(self):
self.assertEqual(testslide.matchers.FloatBetween(2.1, 666), 4.2)
self.assertEqual(testslide.matchers.FloatBetween(2.1, 666), 2.1)
self.assertEqual(testslide.matchers.FloatBetween(21, 66.6), 66.6)
self.assertNotEqual(testslide.matchers.FloatBetween(4.2, 6.9), 66.6)
self.assertNotEqual(testslide.matchers.FloatBetween(4.2, 6.9), "derp")
with self.assertRaises(ValueError):
testslide.matchers.FloatBetween("derp", 42.0)
with self.assertRaises(ValueError):
testslide.matchers.FloatBetween(42, "derp")
with self.assertRaises(ValueError):
testslide.matchers.FloatBetween("derp", "derp")

def test_FloatGreaterThan(self):
self.assertEqual(testslide.matchers.FloatGreaterThan(2.1), 4.2)
self.assertNotEqual(testslide.matchers.FloatGreaterThan(2.1), 2.1)
self.assertNotEqual(testslide.matchers.FloatGreaterThan(2.1), 2.0)
self.assertNotEqual(testslide.matchers.FloatGreaterThan(4.2), "derp")
with self.assertRaises(ValueError):
testslide.matchers.FloatGreaterThan("derp")

def test_FloatGreaterOrEquals(self):
self.assertEqual(testslide.matchers.FloatGreaterOrEquals(2.1), 4.2)
self.assertEqual(testslide.matchers.FloatGreaterOrEquals(2.1), 2.1)
self.assertNotEqual(testslide.matchers.FloatGreaterOrEquals(2.1), 2.0)
self.assertNotEqual(testslide.matchers.FloatGreaterOrEquals(4.2), "derp")
with self.assertRaises(ValueError):
testslide.matchers.FloatGreaterOrEquals("derp")

def test_FloatLessThan(self):
self.assertEqual(testslide.matchers.FloatLessThan(2.1), 2.0)
self.assertNotEqual(testslide.matchers.FloatLessThan(2.1), 2.1)
self.assertNotEqual(testslide.matchers.FloatLessThan(2.1), 2.2)
self.assertNotEqual(testslide.matchers.FloatLessThan(4.2), "derp")
with self.assertRaises(ValueError):
testslide.matchers.FloatLessThan("derp")

def test_FloatLessOrEquals(self):
self.assertEqual(testslide.matchers.FloatLessOrEquals(2.1), 2.0)
self.assertEqual(testslide.matchers.FloatLessOrEquals(2.1), 2.1)
self.assertNotEqual(testslide.matchers.FloatLessOrEquals(2.1), 2.2)
self.assertNotEqual(testslide.matchers.FloatLessOrEquals(4.2), "derp")
with self.assertRaises(ValueError):
testslide.matchers.FloatLessOrEquals("derp")


class GenericTestCase(testslide.TestCase):
Expand Down Expand Up @@ -156,16 +192,28 @@ def testStrContaining(self):
self.assertEqual(testslide.matchers.StrContaining("bot"), "bott")
self.assertNotEqual(testslide.matchers.StrContaining("derp"), "boot")
self.assertNotEqual(testslide.matchers.StrContaining("derp"), 13)
with self.assertRaises(ValueError):
testslide.matchers.StrContaining(10)
with self.assertRaises(ValueError):
testslide.matchers.StrContaining(10.0)

def testStrStartingWith(self):
self.assertEqual(testslide.matchers.StrStartingWith("bo"), "bott")
self.assertNotEqual(testslide.matchers.StrStartingWith("derp"), "boot")
self.assertNotEqual(testslide.matchers.StrStartingWith("derp"), 13)
with self.assertRaises(ValueError):
testslide.matchers.StrStartingWith(10)
with self.assertRaises(ValueError):
testslide.matchers.StrStartingWith(10.0)

def testStrEndingWith(self):
self.assertEqual(testslide.matchers.StrEndingWith("ott"), "bott")
self.assertNotEqual(testslide.matchers.StrEndingWith("derp"), "boot")
self.assertNotEqual(testslide.matchers.StrEndingWith("derp"), 13)
with self.assertRaises(ValueError):
testslide.matchers.StrEndingWith(10)
with self.assertRaises(ValueError):
testslide.matchers.StrEndingWith(10.0)


class TestLists(testslide.TestCase):
Expand All @@ -186,6 +234,12 @@ def testListContainingAll(self):
testslide.matchers.ListContainingAll([1, 2, 3, 5]), [2, 3, 4]
)
self.assertNotEqual(testslide.matchers.ListContainingAll([1, 2, 3, 5]), "DERP")
with self.assertRaises(ValueError):
testslide.matchers.ListContainingAll({"a": "aa", "b": "bb"})
with self.assertRaises(ValueError):
testslide.matchers.ListContainingAll("derp")
with self.assertRaises(ValueError):
testslide.matchers.ListContainingAll(10)


class TestDicts(testslide.TestCase):
Expand Down Expand Up @@ -219,6 +273,12 @@ def testDictSupersetOf(self):
testslide.matchers.DictSupersetOf({"a": "b", "c": 1}), {"c": 1, "d": "e"}
)
self.assertNotEqual(testslide.matchers.DictSupersetOf({}), "DERP")
with self.assertRaises(ValueError):
testslide.matchers.DictSupersetOf(10)
with self.assertRaises(ValueError):
testslide.matchers.DictSupersetOf("derp")
with self.assertRaises(ValueError):
testslide.matchers.DictSupersetOf(["a", "b", "c"])

def testDictContainingKeys(self):
self.assertEqual(
Expand All @@ -229,6 +289,12 @@ def testDictContainingKeys(self):
testslide.matchers.DictContainingKeys(["a", "b", "c"]), {"c": 1, "d": "e"}
)
self.assertNotEqual(testslide.matchers.DictContainingKeys([1, 2]), "DERP")
with self.assertRaises(ValueError):
testslide.matchers.DictContainingKeys(10)
with self.assertRaises(ValueError):
testslide.matchers.DictContainingKeys("derp")
with self.assertRaises(ValueError):
testslide.matchers.DictContainingKeys({"a", "b", "c"})


class TestChaining(testslide.TestCase):
Expand Down
74 changes: 73 additions & 1 deletion testslide/matchers.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,31 +191,55 @@ def __init__(self) -> None:

class NotThisInt(_IntComparison):
def __init__(self, ne: int) -> None:
if not isinstance(ne, int):
raise ValueError(
f"NotThisInt(...) expects an 'int' as argument while '{type(ne).__name__}' was provided"
)
super().__init__(ne=ne)


class IntBetween(_IntComparison):
def __init__(self, lower: int, upper: int) -> None:
if not isinstance(lower, (int, float)) or not isinstance(upper, (int, float)):
raise ValueError(
f"IntBetween(...) expects two numerical values as arguments while '{type(lower).__name__}' and '{type(upper).__name__}' were provided"
)
super().__init__(ge=lower, le=upper)


class IntGreaterThan(_IntComparison):
def __init__(self, gt: int) -> None:
if not isinstance(gt, (int, float)):
raise ValueError(
f"IntGreaterThan(...) expects a numerical value as argument while '{type(gt).__name__}' was provided"
)
super().__init__(gt=gt)


class IntGreaterOrEquals(_IntComparison):
def __init__(self, ge: int) -> None:
if not isinstance(ge, (int, float)):
raise ValueError(
f"IntGreaterOrEquals(...) expects a numerical value as argument while '{type(ge).__name__}' was provided"
)
super().__init__(ge=ge)


class IntLessThan(_IntComparison):
def __init__(self, lt: int) -> None:
if not isinstance(lt, (int, float)):
raise ValueError(
f"IntLessThan(...) expects a numerical value as argument while '{type(lt).__name__}' was provided"
)
super().__init__(lt=lt)


class IntLessOrEquals(_IntComparison):
def __init__(self, le: int) -> None:
if not isinstance(le, (int, float)):
raise ValueError(
f"IntLessOrEquals(...) expects a numerical value as argument while '{type(le).__name__}' was provided"
)
super().__init__(le=le)


Expand All @@ -227,31 +251,55 @@ def __init__(self) -> None:

class NotThisFloat(_FloatComparison):
def __init__(self, ne: float) -> None:
if not isinstance(ne, float):
raise ValueError(
f"NotThisFloat(...) expects a 'float' as argument while '{type(ne).__name__}' was provided"
)
super().__init__(ne=ne)


class FloatBetween(_FloatComparison):
def __init__(self, lower: float, upper: float) -> None:
if not isinstance(lower, (int, float)) or not isinstance(upper, (int, float)):
raise ValueError(
f"FloatBetween(...) expects numerical values as arguments while '{type(lower).__name__}' and '{type(upper).__name__}' were provided"
)
super().__init__(ge=lower, le=upper)


class FloatGreaterThan(_FloatComparison):
def __init__(self, gt: float) -> None:
if not isinstance(gt, (int, float)):
raise ValueError(
f"FloatGreaterThan(...) expects a numerical value as argument while '{type(gt).__name__}' was provided"
)
super().__init__(gt=gt)


class FloatGreaterOrEquals(_FloatComparison):
def __init__(self, ge: float) -> None:
if not isinstance(ge, (int, float)):
raise ValueError(
f"FloatGreaterOrEquals(...) expects a numerical value as argument while '{type(ge).__name__}' was provided"
)
super().__init__(ge=ge)


class FloatLessThan(_FloatComparison):
def __init__(self, lt: float) -> None:
if not isinstance(lt, (int, float)):
raise ValueError(
f"FloatLessThan(...) expects a numerical value as argument while '{type(lt).__name__}' was provided"
)
super().__init__(lt=lt)


class FloatLessOrEquals(_FloatComparison):
def __init__(self, le: float) -> None:
if not isinstance(le, (int, float)):
raise ValueError(
f"FloatLessOrEquals(...) expects a numerical value as argument while '{type(le).__name__}' was provided"
)
super().__init__(le=le)


Expand All @@ -265,7 +313,7 @@ def __init__(self) -> None:

class RegexMatches(Matcher):
"""
Compares true if other mathes given regex.
Compares true if other matches given regex.
"""

def __init__(self, pattern: str, flags: int = 0) -> None:
Expand All @@ -288,6 +336,10 @@ def __repr__(self) -> str:

class StrContaining(Matcher):
def __init__(self, needle: str) -> None:
if not isinstance(needle, str):
raise ValueError(
f"StrContaining(...) expects a 'str' as argument while '{type(needle).__name__}' was provided"
)
self.needle = needle

def __eq__(self, other: AnyType) -> bool:
Expand All @@ -296,6 +348,10 @@ def __eq__(self, other: AnyType) -> bool:

class StrStartingWith(Matcher):
def __init__(self, needle: str) -> None:
if not isinstance(needle, str):
raise ValueError(
f"StrStartingWith(...) expects a 'str' as argument while '{type(needle).__name__}' was provided"
)
self.needle = needle

def __eq__(self, other: AnyType) -> bool:
Expand All @@ -304,6 +360,10 @@ def __eq__(self, other: AnyType) -> bool:

class StrEndingWith(Matcher):
def __init__(self, needle: str) -> None:
if not isinstance(needle, str):
raise ValueError(
f"StrEndingWith(...) expects a 'str' as argument while '{type(needle).__name__}' was provided"
)
self.needle = needle

def __eq__(self, other: AnyType) -> bool: # type: ignore
Expand Down Expand Up @@ -334,6 +394,10 @@ def __repr__(self) -> str:

class ListContainingAll(_RichComparison):
def __init__(self, subset: List[AnyType]) -> None:
if not isinstance(subset, list):
raise ValueError(
f"ListContainingAll(...) expects a 'list' as argument while '{type(subset).__name__}' was provided"
)
self.subset = subset
super().__init__(klass=List)

Expand Down Expand Up @@ -376,6 +440,10 @@ def __eq__(self, other: Optional[Dict[AnyType, AnyType]]) -> bool: # type: igno

class DictContainingKeys(_RichComparison):
def __init__(self, expected_keys: List[AnyType]) -> None:
if not isinstance(expected_keys, list):
raise ValueError(
f"DictContainingKeys(...) expects a 'list' as argument while '{type(expected_keys).__name__}' was provided"
)
self.expected_keys = expected_keys
super().__init__(klass=Dict)

Expand All @@ -390,6 +458,10 @@ def __eq__(self, other: Dict[AnyType, AnyType]) -> bool: # type: ignore

class DictSupersetOf(_RichComparison):
def __init__(self, subset: Dict[AnyType, AnyType]) -> None:
if not isinstance(subset, dict):
raise ValueError(
f"DictSupersetOf(...) expects a 'dict' as argument while '{type(subset).__name__}' was provided"
)
self.subset = subset
super().__init__(klass=Dict)

Expand Down

0 comments on commit aa4a514

Please sign in to comment.