Skip to content

Commit 464e299

Browse files
add unit tests
1 parent c07764f commit 464e299

2 files changed

Lines changed: 46 additions & 10 deletions

File tree

openhtf/util/validators.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -446,10 +446,9 @@ def __init__(self, regex_list: list[str], compiled_list: list[re.Pattern]) -> No
446446
self.regex_list = regex_list
447447
self._compiled_list = compiled_list
448448

449-
def __call__(self, value: str) -> bool:
450-
str_value = str(value)
449+
def __call__(self, candidate_str: str) -> bool:
451450
for compiled_pattern in self._compiled_list:
452-
if compiled_pattern.match(str_value) is not None:
451+
if compiled_pattern.match(candidate_str):
453452
return True
454453
return False
455454

@@ -467,22 +466,19 @@ def __ne__(self, other) -> bool:
467466
return not self == other
468467

469468
@register
470-
def matches_any_regex(*regex_lists: list[list[str]]):
469+
def matches_any_regex(*regex_lists: tuple[list[str]]):
471470
"""
472471
Creates a validator that checks if a value matches ANY of the provided regex patterns.
473-
474-
Accepts one or more lists of regex strings.
475-
Example: matches_any_regex(['a.*'], ['b.*', 'c.*'])
476472
"""
477-
# 1. Amalgamate all lists into a single flat list of regex strings
473+
478474
flat_regex_list = []
479475
for regex_list in regex_lists:
476+
if not isinstance(regex_list, list) or not regex_list:
477+
raise ValueError("Each argument must be a list of regex patterns.")
480478
flat_regex_list.extend(regex_list)
481479

482-
# 2. Compile the flat list of regex strings
483480
compiled_list = [re.compile(regex) for regex in flat_regex_list]
484481

485-
# 3. Pass both the original flat list and the compiled list to the matcher
486482
return MultiRegexMatcher(flat_regex_list, compiled_list)
487483

488484
class WithinPercent(RangeValidatorBase):

test/util/validators_test.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,42 @@ def test_with_custom_type(self):
7878
self.assertEqual(test_validator.maximum, 0x12)
7979

8080

81+
class TestSingleRegex(unittest.TestCase):
82+
def test_single_regex(self):
83+
pattern = r'^[A-Z]{3}\d{3}$'
84+
validator = validators.matches_regex(pattern)
85+
self.assertTrue(validator('ABC123'))
86+
self.assertFalse(validator('abc123'))
87+
self.assertFalse(validator('AB1234'))
88+
self.assertFalse(validator('ABCD12'))
89+
90+
91+
class TestMultipleRegex(unittest.TestCase):
92+
patterns_1 = [r'^[A-Z]{1}\d{1}$', r'^[A-Z]{2}\d{2}$', r'^[A-Z]{3}\d{3}$']
93+
patterns_2 = [r'^\d{1}[A-Z]{1}$']
94+
def test_multiple_regex_lists(self):
95+
96+
validator_1 = validators.matches_any_regex(TestMultipleRegex.patterns_1, TestMultipleRegex.patterns_2)
97+
self.assertTrue(validator_1('ABC123'))
98+
self.assertTrue(validator_1('A1'))
99+
self.assertTrue(validator_1('1A'))
100+
self.assertFalse(validator_1('123-ABCD'))
101+
102+
def test_single_regex_list(self):
103+
validator_2 = validators.matches_any_regex(TestMultipleRegex.patterns_2)
104+
self.assertTrue(validator_2('1A'))
105+
self.assertFalse(validator_2('A1'))
106+
107+
def test_invalid_arguments(self):
108+
with self.assertRaisesRegex(ValueError, "Each argument must be a list of regex patterns."):
109+
validators.matches_any_regex(r'^[A-Z]{3}\d{3}$')
110+
111+
with self.assertRaisesRegex(ValueError, "Each argument must be a list of regex patterns."):
112+
validators.matches_any_regex([])
113+
114+
with self.assertRaisesRegex(ValueError, "Each argument must be a list of regex patterns."):
115+
validators.matches_any_regex(r'd{3}', r'd{4}')
116+
81117
class TestAllInRange(unittest.TestCase):
82118

83119
def setUp(self):
@@ -395,3 +431,7 @@ def phase(test):
395431

396432
phase_record = yield phase
397433
self.assertMeasurementFail(phase_record, 'pivot')
434+
435+
if __name__ == '__main__':
436+
from unittest import main
437+
main()

0 commit comments

Comments
 (0)