Skip to content

Commit a69a78b

Browse files
pszulczewskiPatryk Szulczewski
andauthored
Added exception tests + refactor in arguments. (#30)
* Added exception tests + refactor in arguments. * remove test print() Co-authored-by: Patryk Szulczewski <patryk.szulczewski@networktocode.com>
1 parent 6d5eb8e commit a69a78b

File tree

3 files changed

+59
-43
lines changed

3 files changed

+59
-43
lines changed

netcompare/check_types.py

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,13 @@ def __init__(self, *args):
121121
super().__init__()
122122

123123
try:
124-
tolerance = args[1]
124+
tolerance = float(args[1])
125125
except IndexError as error:
126-
raise ValueError(f"Tolerance parameter must be defined as float at index 1. You have: {args}") from error
127-
self.tolerance_factor = float(tolerance) / 100
126+
raise IndexError(f"Tolerance parameter must be defined as float at index 1. You have: {args}") from error
127+
except ValueError as error:
128+
raise ValueError(f"Argument must be convertible to float. You have: {args[1]}") from error
129+
130+
self.tolerance_factor = tolerance / 100
128131

129132
def evaluate(self, reference_value: Mapping, value_to_compare: Mapping) -> Tuple[Dict, bool]:
130133
"""Returns the difference between values and the boolean. Overwrites method in base class."""
@@ -155,16 +158,10 @@ class ParameterMatchType(CheckType):
155158

156159
def evaluate(self, reference_value: Mapping, value_to_compare: Mapping) -> Tuple[Dict, bool]:
157160
"""Parameter Match evaluator implementation."""
158-
try:
159-
parameter = value_to_compare[1]
160-
except IndexError as error:
161-
raise ValueError(
162-
f"Evaluating parameter must be defined as dict at index 1. You have: {value_to_compare}"
163-
) from error
164-
if not isinstance(parameter, dict):
161+
if not isinstance(value_to_compare, dict):
165162
raise TypeError("check_option must be of type dict()")
166163

167-
evaluation_result = parameter_evaluator(reference_value, parameter)
164+
evaluation_result = parameter_evaluator(reference_value, value_to_compare)
168165
return evaluation_result, not evaluation_result
169166

170167

@@ -173,29 +170,21 @@ class RegexType(CheckType):
173170

174171
def evaluate(self, reference_value: Mapping, value_to_compare: Mapping) -> Tuple[Mapping, bool]:
175172
"""Regex Match evaluator implementation."""
176-
# Assert that check parameters are at index 1.
177-
try:
178-
parameter = value_to_compare[1]
179-
except IndexError as error:
180-
raise IndexError(
181-
f"Evaluating parameter must be defined as dict at index 1. You have: {value_to_compare}"
182-
) from error
183-
184-
# Assert that check parameters are at index 1.
185-
if not all([isinstance(parameter, dict)]):
173+
# Check that check value_to_compare is dict.
174+
if not isinstance(value_to_compare, dict):
186175
raise TypeError("check_option must be of type dict().")
187176

188-
# Assert that check option has 'regex' and 'mode' dict keys.
189-
if "regex" not in parameter and "mode" not in parameter:
177+
# Check that value_to_compare has 'regex' and 'mode' dict keys.
178+
if any(key not in value_to_compare.keys() for key in ("regex", "mode")):
190179
raise KeyError(
191180
"Regex check-type requires check-option. Example: dict(regex='.*UNDERLAY.*', mode='no-match')."
192181
)
193182

194183
# Assert that check option has 'regex' and 'mode' dict keys.\
195-
if parameter["mode"] not in ["match", "no-match"]:
184+
if value_to_compare["mode"] not in ["match", "no-match"]:
196185
raise ValueError(
197186
"Regex check-type requires check-option. Example: dict(regex='.*UNDERLAY.*', mode='no-match')."
198187
)
199188

200-
diff = regex_evaluator(reference_value, parameter)
189+
diff = regex_evaluator(reference_value, value_to_compare)
201190
return diff, not diff

netcompare/evaluators.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ def regex_evaluator(values: Mapping, parameter: Mapping) -> Dict:
8585
# parameter: {'regex': '.*UNDERLAY.*', 'mode': 'include'}
8686
result = {}
8787
if not isinstance(values, list):
88-
raise TypeError("Something went wrong during JMSPath parsing. values must be of type list.")
88+
raise TypeError("Something went wrong during JMSPath parsing. 'values' must be of type List.")
8989

9090
regex_expression = parameter["regex"]
9191
mode = parameter["mode"]

tests/test_type_checks.py

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,39 @@ def test_check_init(args, expected_class):
1313
assert isinstance(CheckType.init(*args), expected_class)
1414

1515

16-
def test_check_type_raises_not_implemented_error_for_invalid_check_type():
17-
"""Validate that CheckType raises a NotImplementedError when passed a non-existant check_type."""
18-
with pytest.raises(NotImplementedError):
19-
CheckType.init("does_not_exist")
16+
exception_tests_init = [
17+
(("does_not_exist",), NotImplementedError, ""),
18+
(("tolerance",), IndexError, "parameter"),
19+
(("tolerance", "non-float"), ValueError, "non-float"),
20+
]
21+
22+
23+
@pytest.mark.parametrize("check_type_args, exception_type, expected_in_output", exception_tests_init)
24+
def tests_exceptions_init(check_type_args, exception_type, expected_in_output):
25+
"""Tests exceptions when check object is initialized."""
26+
with pytest.raises(exception_type) as error:
27+
CheckType.init(*check_type_args)
28+
assert expected_in_output in error.value.__str__()
29+
30+
31+
exception_tests_eval = [
32+
("parameter_match", ([{}], "not-dict"), TypeError, "dict()"),
33+
("parameter_match", ({}, {}), TypeError, "'values' must be of type List"),
34+
("regex", ([{}], "not-dict"), TypeError, "dict()"),
35+
("regex", ([{}], {"mode": "match"}), KeyError, "check-option"),
36+
("regex", ([{}], {"mode": "regex"}), KeyError, "check-option"),
37+
("regex", ([{}], {"regex": "", "mode": "unknown"}), ValueError, "check-option"),
38+
("regex", ({}, {"regex": "", "mode": "match"}), TypeError, "'values' must be of type List"),
39+
]
40+
41+
42+
@pytest.mark.parametrize("check_type, args, exception_type, expected_in_output", exception_tests_eval)
43+
def tests_exceptions_eval(check_type, args, exception_type, expected_in_output):
44+
"""Tests exceptions when calling .evaluate() method."""
45+
with pytest.raises(exception_type) as error:
46+
check = CheckType.init(check_type)
47+
check.evaluate(*args)
48+
assert expected_in_output in error.value.__str__()
2049

2150

2251
exact_match_test_values_no_change = (
@@ -187,12 +216,10 @@ def test_check_type_results(check_type_args, folder_name, path, expected_results
187216
]
188217

189218

190-
@pytest.mark.parametrize("folder_name, check_args, path, expected_result", check_tests)
191-
def test_checks(folder_name, check_args, path, expected_result):
219+
@pytest.mark.parametrize("folder_name, check_type_args, path, expected_result", check_tests)
220+
def test_checks(folder_name, check_type_args, path, expected_result):
192221
"""Validate multiple checks on the same data to catch corner cases."""
193-
pre_data, post_data = load_mocks(folder_name)
194-
195-
check = CheckType.init(*check_args)
222+
check = CheckType.init(*check_type_args)
196223
pre_data, post_data = load_mocks(folder_name)
197224
pre_value = check.get_value(pre_data, path)
198225
post_value = check.get_value(post_data, path)
@@ -217,14 +244,14 @@ def test_checks(folder_name, check_args, path, expected_result):
217244
)
218245

219246

220-
@pytest.mark.parametrize("filename, check_args, path, expected_result", [parameter_match_api])
221-
def test_param_match(filename, check_args, path, expected_result):
247+
@pytest.mark.parametrize("filename, check_type_args, path, expected_result", [parameter_match_api])
248+
def test_param_match(filename, check_type_args, path, expected_result):
222249
"""Validate parameter_match check type."""
223-
check = CheckType.init(*check_args)
250+
check = CheckType.init(check_type_args[0])
224251
# There is not concept of "pre" and "post" in parameter_match.
225252
data = load_json_file("parameter_match", filename)
226253
value = check.get_value(data, path)
227-
actual_results = check.evaluate(value, check_args)
254+
actual_results = check.evaluate(value, check_type_args[1])
228255
assert actual_results == expected_result, ASSERT_FAIL_MESSAGE.format(
229256
output=actual_results, expected_output=expected_result
230257
)
@@ -262,14 +289,14 @@ def test_param_match(filename, check_args, path, expected_result):
262289
]
263290

264291

265-
@pytest.mark.parametrize("filename, check_args, path, expected_result", regex_match)
266-
def test_regex_match(filename, check_args, path, expected_result):
292+
@pytest.mark.parametrize("filename, check_type_args, path, expected_result", regex_match)
293+
def test_regex_match(filename, check_type_args, path, expected_result):
267294
"""Validate regex check type."""
268-
check = CheckType.init(*check_args)
295+
check = CheckType.init(check_type_args[0])
269296
# There is not concept of "pre" and "post" in parameter_match.
270297
data = load_json_file("api", filename)
271298
value = check.get_value(data, path)
272-
actual_results = check.evaluate(value, check_args)
299+
actual_results = check.evaluate(value, check_type_args[1])
273300
assert actual_results == expected_result, ASSERT_FAIL_MESSAGE.format(
274301
output=actual_results, expected_output=expected_result
275302
)

0 commit comments

Comments
 (0)