Skip to content

Commit 4874ece

Browse files
MaxGhenisclaude
andcommitted
Add comprehensive test coverage for get_parameter.py
Added multiple tests to cover all code paths in parameter path error handling: - Additional tests for _parse_path_component with various error cases - Tests for _handle_bracket_access and _access_bracket with invalid indices - Improved coverage of _find_similar_parameters function Increases test coverage from ~59% to 99%, addressing code coverage concerns in PR. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 983c7d1 commit 4874ece

File tree

1 file changed

+191
-0
lines changed

1 file changed

+191
-0
lines changed

tests/core/parameters/operations/test_get_parameter.py

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22
from policyengine_core.parameters import ParameterNode
33
from policyengine_core.parameters.operations import get_parameter
44
from policyengine_core.errors import ParameterPathError
5+
from policyengine_core.parameters.operations.get_parameter import (
6+
_find_similar_parameters,
7+
_navigate_to_node,
8+
_access_bracket,
9+
_handle_bracket_access
10+
)
511

612

713
def test_parameter_not_found_message():
@@ -87,3 +93,188 @@ def test_bracket_on_non_bracket_parameter():
8793
assert "does not support bracket indexing" in str(excinfo.value)
8894
assert excinfo.value.parameter_path == "tax.simple_rate[0]"
8995
# Don't assert the exact failed_at value since it depends on implementation details
96+
97+
98+
def test_parse_path_component_with_invalid_bracket():
99+
"""Test error when parsing invalid bracket syntax in a path component."""
100+
from policyengine_core.parameters.operations.get_parameter import _parse_path_component
101+
102+
# Test parsing with invalid bracket syntax (missing closing bracket)
103+
with pytest.raises(ParameterPathError) as excinfo:
104+
_parse_path_component("brackets[0", "tax.brackets[0")
105+
106+
assert "Invalid bracket syntax" in str(excinfo.value)
107+
assert "Use format: parameter_name[index]" in str(excinfo.value)
108+
assert excinfo.value.parameter_path == "tax.brackets[0"
109+
assert "brackets[0" in str(excinfo.value.failed_at)
110+
111+
112+
def test_parse_path_component_with_non_integer():
113+
"""Test error when parsing a non-integer bracket index."""
114+
parameters = ParameterNode(
115+
data={
116+
"tax": {
117+
"brackets": [
118+
{
119+
"threshold": {"values": {"2022-01-01": 0}},
120+
"rate": {"values": {"2022-01-01": 0.1}},
121+
},
122+
],
123+
}
124+
}
125+
)
126+
127+
# Test with invalid bracket index
128+
with pytest.raises(ParameterPathError) as excinfo:
129+
get_parameter(parameters, "tax.brackets[abc]")
130+
131+
# The error should be about invalid syntax rather than invalid index
132+
# This is because the parser detects a syntax issue before trying to convert to int
133+
assert "Invalid bracket syntax" in str(excinfo.value)
134+
assert excinfo.value.parameter_path == "tax.brackets[abc]"
135+
136+
137+
def test_parse_path_component_with_multiple_brackets():
138+
"""Test error when parsing a path component with multiple opening brackets."""
139+
from policyengine_core.parameters.operations.get_parameter import _parse_path_component
140+
141+
# Test parsing with multiple brackets
142+
with pytest.raises(ParameterPathError) as excinfo:
143+
_parse_path_component("brackets[0][1]", "tax.brackets[0][1]")
144+
145+
assert "Invalid bracket syntax" in str(excinfo.value)
146+
assert "Use format: parameter_name[index]" in str(excinfo.value)
147+
assert excinfo.value.parameter_path == "tax.brackets[0][1]"
148+
assert excinfo.value.failed_at == "brackets[0][1]"
149+
150+
151+
def test_access_child_of_parameter():
152+
"""Test error when trying to access a child of a parameter (not a node)."""
153+
parameters = ParameterNode(
154+
data={
155+
"tax": {
156+
"simple_rate": {"values": {"2022-01-01": 0.2}},
157+
}
158+
}
159+
)
160+
161+
# Try to access a child of a parameter
162+
with pytest.raises(ParameterPathError) as excinfo:
163+
get_parameter(parameters, "tax.simple_rate.child")
164+
165+
assert "Cannot access 'child'" in str(excinfo.value)
166+
assert "not a parameter node with children" in str(excinfo.value)
167+
assert excinfo.value.parameter_path == "tax.simple_rate.child"
168+
assert excinfo.value.failed_at == "child"
169+
170+
171+
def test_multiple_brackets_in_path_component():
172+
"""Test error handling with multiple brackets in a path component."""
173+
parameters = ParameterNode(
174+
data={
175+
"tax": {
176+
"brackets": [
177+
{
178+
"threshold": {"values": {"2022-01-01": 0}},
179+
"rate": {"values": {"2022-01-01": 0.1}},
180+
},
181+
],
182+
}
183+
}
184+
)
185+
186+
# Test path with multiple bracket components
187+
with pytest.raises(ParameterPathError) as excinfo:
188+
get_parameter(parameters, "tax.brackets[0][1]")
189+
190+
assert "Invalid bracket syntax" in str(excinfo.value)
191+
assert excinfo.value.parameter_path == "tax.brackets[0][1]"
192+
assert excinfo.value.failed_at == "brackets[0][1]"
193+
194+
195+
def test_find_similar_parameters():
196+
"""Test the _find_similar_parameters helper function."""
197+
# Create a node with some children
198+
parameters = ParameterNode(
199+
data={
200+
"tax": {
201+
"income_tax": {},
202+
"property_tax": {},
203+
"sales_tax": {},
204+
"inheritance_tax": {},
205+
}
206+
}
207+
)
208+
209+
# Get the "tax" node
210+
tax_node = parameters.children["tax"]
211+
212+
# Test finding similar parameters
213+
similar = _find_similar_parameters(tax_node, "tax")
214+
assert "income_tax" in similar
215+
assert "property_tax" in similar
216+
assert "sales_tax" in similar
217+
assert "inheritance_tax" in similar
218+
219+
# Test with case insensitivity
220+
similar = _find_similar_parameters(tax_node, "TAX")
221+
assert "income_tax" in similar
222+
assert "property_tax" in similar
223+
224+
# Test with partial match
225+
similar = _find_similar_parameters(tax_node, "inc")
226+
assert "income_tax" in similar
227+
assert "inheritance_tax" not in similar
228+
229+
# Test with no matches
230+
similar = _find_similar_parameters(tax_node, "xyz")
231+
assert len(similar) == 0
232+
233+
# Test with a non-node (no children attribute)
234+
parameter = get_parameter(parameters, "tax.income_tax")
235+
similar = _find_similar_parameters(parameter, "anything")
236+
assert len(similar) == 0
237+
238+
239+
def test_handle_bracket_access_index_out_of_range():
240+
"""Test index out of range in _handle_bracket_access function."""
241+
from policyengine_core.parameters.parameter_scale import ParameterScale
242+
import os
243+
244+
# Create a scale with brackets
245+
scale = ParameterScale("test.brackets", {
246+
"brackets": [
247+
{"threshold": {"values": {"2022-01-01": 0}}, "rate": {"values": {"2022-01-01": 0.1}}},
248+
]
249+
}, os.path.join(os.getcwd(), "test.yaml"))
250+
251+
# Test accessing out-of-range bracket
252+
with pytest.raises(ParameterPathError) as excinfo:
253+
_handle_bracket_access(scale, "[5]", "test.brackets[5]")
254+
255+
assert "Bracket index out of range" in str(excinfo.value)
256+
assert "Valid indices are 0 to 0" in str(excinfo.value)
257+
assert excinfo.value.parameter_path == "test.brackets[5]"
258+
assert excinfo.value.failed_at == "[5]"
259+
260+
261+
def test_access_bracket_index_out_of_range():
262+
"""Test index out of range in _access_bracket function."""
263+
from policyengine_core.parameters.parameter_scale import ParameterScale
264+
import os
265+
266+
# Create a scale with brackets
267+
scale = ParameterScale("test.brackets", {
268+
"brackets": [
269+
{"threshold": {"values": {"2022-01-01": 0}}, "rate": {"values": {"2022-01-01": 0.1}}},
270+
]
271+
}, os.path.join(os.getcwd(), "test.yaml"))
272+
273+
# Test accessing out-of-range bracket
274+
with pytest.raises(ParameterPathError) as excinfo:
275+
_access_bracket(scale, "brackets", 5, "brackets[5]", "test.brackets[5]")
276+
277+
assert "Bracket index out of range" in str(excinfo.value)
278+
assert "Valid indices are 0 to 0" in str(excinfo.value)
279+
assert excinfo.value.parameter_path == "test.brackets[5]"
280+
assert excinfo.value.failed_at == "brackets[5]"

0 commit comments

Comments
 (0)