Skip to content

Commit

Permalink
Add model tests
Browse files Browse the repository at this point in the history
  • Loading branch information
timmens committed Sep 4, 2024
1 parent 9c877fd commit 4059f7d
Show file tree
Hide file tree
Showing 2 changed files with 149 additions and 3 deletions.
8 changes: 5 additions & 3 deletions src/lcm/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,11 @@ def _validate_attribute_types(model: Model) -> list[str]:
else:
for k, v in model.functions.items():
if not isinstance(k, str):
error_messages.append(f"functions key {k} must be a string.")
error_messages.append(f"function keys must be a strings, but is {k}.")
if not callable(v):
error_messages.append(f"functions value {v} must be a callable.")
error_messages.append(
f"function values must be a callable, but is {v}."
)

return error_messages

Expand All @@ -96,7 +98,7 @@ def _validate_logical_consistency(model: Model) -> list[str]:

if "utility" not in model.functions:
error_messages.append(
"Utility function is not defined. LCM expects a function called 'utility'"
"Utility function is not defined. LCM expects a function called 'utility' "
"in the functions dictionary.",
)

Expand Down
144 changes: 144 additions & 0 deletions tests/test_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import pytest

from lcm.exceptions import ModelInitilizationError
from lcm.grids import DiscreteGrid
from lcm.model import Model


def test_model_invalid_states():
with pytest.raises(ModelInitilizationError, match="states must be a dictionary"):
Model(
n_periods=2,
states="health",
choices={},
functions={"utility": lambda: 0},
)


def test_model_invalid_choices():
with pytest.raises(ModelInitilizationError, match="choices must be a dictionary"):
Model(
n_periods=2,
states={},
choices="exercise",
functions={"utility": lambda: 0},
)


def test_model_invalid_functions():
with pytest.raises(ModelInitilizationError, match="functions must be a dictionary"):
Model(
n_periods=2,
states={},
choices={},
functions="utility",
)


def test_model_invalid_functions_values():
with pytest.raises(
ModelInitilizationError, match="function values must be a callable, but is 0."
):
Model(
n_periods=2,
states={},
choices={},
functions={"utility": 0},
)


def test_model_invalid_functions_keys():
with pytest.raises(
ModelInitilizationError, match="function keys must be a strings, but is 0."
):
Model(
n_periods=2,
states={},
choices={},
functions={0: lambda: 0},
)


def test_model_invalid_choices_values():
with pytest.raises(
ModelInitilizationError, match="choices value 0 must be an LCM grid."
):
Model(
n_periods=2,
states={},
choices={"exercise": 0},
functions={"utility": lambda: 0},
)


def test_model_invalid_states_values():
with pytest.raises(
ModelInitilizationError, match="states value 0 must be an LCM grid."
):
Model(
n_periods=2,
states={"health": 0},
choices={},
functions={"utility": lambda: 0},
)


def test_model_invalid_n_periods():
with pytest.raises(
ModelInitilizationError, match="Number of periods must be a positive integer."
):
Model(
n_periods=0,
states={},
choices={},
functions={"utility": lambda: 0},
)


def test_model_missing_next_func():
with pytest.raises(
ModelInitilizationError,
match="Each state must have a corresponding next state function.",
):
Model(
n_periods=2,
states={"health": DiscreteGrid([0, 1])},
choices={"exercise": DiscreteGrid([0, 1])},
functions={"utility": lambda: 0},
)


def test_model_missing_utility():
with pytest.raises(
ModelInitilizationError,
match="Utility function is not defined. LCM expects a function called 'utility",
):
Model(
n_periods=2,
states={},
choices={},
functions={},
)


def test_model_overlapping_states_choices():
with pytest.raises(
ModelInitilizationError,
match="States and choices cannot have overlapping names.",
):
Model(
n_periods=2,
states={"health": DiscreteGrid([0, 1])},
choices={"health": DiscreteGrid([0, 1])},
functions={"utility": lambda: 0},
)


def test_model_skip_checks():
Model(
n_periods=-1, # invalid number of periods
states={},
choices={},
functions={"utility": lambda: 0},
_skip_checks=True,
)

0 comments on commit 4059f7d

Please sign in to comment.