diff --git a/src/lib_brecal_utils/brecal_utils/validators/schema_validation.py b/src/lib_brecal_utils/brecal_utils/validators/schema_validation.py index 4be37f6..e47d59a 100644 --- a/src/lib_brecal_utils/brecal_utils/validators/schema_validation.py +++ b/src/lib_brecal_utils/brecal_utils/validators/schema_validation.py @@ -35,11 +35,22 @@ def length_matches_exactly(query_value, length_value): ### Ship dataclass (BreCal.schema.model.Ship) ### -@validation_state_and_validation_name("ship_bollard_pull") -def ship_bollard_is_none_or_in_range(ship): +@validation_state_and_validation_name("ship_bollard_pull_none_or_value_in_range") +def ship_bollard_pull_is_none_or_in_range(ship): """a ship should either have its bollard_pull between 0 and 500, or have an undefined bollard_pull (when not a tug)""" return (ship.bollard_pull is None) or (value_in_range(ship.bollard_pull, 0, 500)) +@validation_state_and_validation_name("ship_max_draft_none_or_value_in_range") +def ship_max_draft_is_none_or_in_range(ship): + """a ship should either have its max_draft between 0 and 20, or have an undefined max_draft (when not a tug)""" + return (ship.max_draft is None) or (value_in_range(ship.max_draft, 0, 20)) + +@validation_state_and_validation_name("ship_participant_id_none_or_int") +def ship_participant_id_is_none_or_int(ship): + """a ship should either have its participant_id defined (integer when ship is a tug), or have an undefined participant_id (when not a tug)""" + return isinstance(ship.participant_id, int) or (ship.participant_id is None) + + @validation_state_and_validation_name("ship_length") def ship_length_in_range(ship): """ship length-values should be valid. between 0 and 500 meters is plausible. returns bool""" @@ -50,11 +61,6 @@ def ship_width_in_range(ship): """ship length-values should be valid. between 0 and 500 meters is plausible. returns bool""" return value_in_range(ship.width, 0, 500) -@validation_state_and_validation_name("ship_max_draft") -def ship_max_draft_in_range(ship): - """ship max_draft-values should be valid. between 0 and 500 meters is plausible. returns bool""" - return value_in_range(ship.max_draft, 0, 20) - @validation_state_and_validation_name("ship_eni_length") def ship_eni_len_is_eight(ship): """eni-no. are standardized. They should have exactly eight characters. returns bool""" diff --git a/src/lib_brecal_utils/tests/validators/__init__.py b/src/lib_brecal_utils/tests/validators/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/lib_brecal_utils/tests/validators/test_schema_validation.py b/src/lib_brecal_utils/tests/validators/test_schema_validation.py new file mode 100644 index 0000000..3341407 --- /dev/null +++ b/src/lib_brecal_utils/tests/validators/test_schema_validation.py @@ -0,0 +1,240 @@ +import pytest +from brecal_utils.stubs.ship import get_ship_simple +from brecal_utils.validators.schema_validation import ship_length_in_range, ship_width_in_range, ship_bollard_pull_is_none_or_in_range, ship_participant_id_is_none_or_int, ship_max_draft_is_none_or_in_range, ship_eni_len_is_eight, ship_callsign_len_is_seven_at_maximum, ship_imo_len_is_seven, ship_bollard_pull_is_defined_or_is_not_tug, ship_max_draft_is_defined_or_is_not_tug, ship_participant_id_is_defined_or_is_not_tug + +def test_ship_length_valid_range_234_is_valid(): + ship = get_ship_simple() + ship.length = 234 + assert ship_length_in_range(ship)[0], f"ship length must be between 0 and 500 meters" + return + +def test_ship_length_maximum_not_valid_range(): + ship = get_ship_simple() + ship.length = 500 + with pytest.raises(AssertionError): + assert ship_length_in_range(ship)[0], f"ship length must be between 0 and 500 meters, but is 500" + return + +def test_ship_length_minimum_not_valid_range(): + ship = get_ship_simple() + ship.length = 0 + with pytest.raises(AssertionError): + assert ship_length_in_range(ship)[0], f"ship length must be between 0 and 500 meters, but is 0" + return + +def test_ship_width_valid_range_137_is_valid(): + ship = get_ship_simple() + ship.width = 137 + assert ship_width_in_range(ship)[0], f"ship width must be between 0 and 500 meters" + return + +def test_ship_width_maximum_not_valid_range(): + ship = get_ship_simple() + ship.width = 500 + with pytest.raises(AssertionError): + assert ship_width_in_range(ship)[0], f"ship width must be between 0 and 500 meters, but is 500" + return + +def test_ship_width_minimum_not_valid_range(): + ship = get_ship_simple() + ship.width = 0 + with pytest.raises(AssertionError): + assert ship_width_in_range(ship)[0], f"ship width must be between 0 and 500 meters, but is 0" + return + +# not tug: values can be None and raise no error +def test_ship_bollard_pull_is_none_and_not_tug(): + ship = get_ship_simple() + ship.is_tug = False + ship.bollard_pull = None + assert ship_bollard_pull_is_none_or_in_range(ship)[0], f"the bollard_pull should either be undefined or between 0 and 500 meters" + return + +def test_ship_participant_id_is_none_and_not_tug(): + ship = get_ship_simple() + ship.is_tug = False + ship.participant_id = None + assert ship_participant_id_is_none_or_int(ship)[0], f"the participant_id should either be undefined or an integer id" + return + +def test_ship_max_draft_is_none_and_not_tug(): + ship = get_ship_simple() + ship.is_tug = False + ship.max_draft = None + assert ship_max_draft_is_none_or_in_range(ship)[0], f"the max_draft should either be undefined or between 0 and 20 meters" + return + + +# tug: values must be set, and are set. all tests should be accepted without assertion +def test_ship_is_tug_bollard_pull_is_not_none(): + ship = get_ship_simple() + ship.is_tug = True + ship.bollard_pull = 311 + assert ship_bollard_pull_is_none_or_in_range(ship)[0], f"the bollard_pull should either be undefined or between 0 and 500 meters" + return + + +def test_ship_is_tug_max_draft_is_not_none(): + ship = get_ship_simple() + ship.is_tug = True + ship.max_draft = 17 + assert ship_max_draft_is_none_or_in_range(ship)[0], f"the max_draft should either be undefined or between 0 and 20 meters" + return + +def test_ship_is_tug_participant_id_is_not_none(): + from brecal_utils.stubs import generate_uuid1_int + ship = get_ship_simple() + ship.is_tug = True + ship.participant_id = generate_uuid1_int() + assert ship_participant_id_is_none_or_int(ship)[0], f"the participant_id should either be undefined or an integer id" + return + +def test_ship_is_tug_participant_id_is_str_and_fails(): + # note: this is an artificial test case. However, it ensures that operators using the backend cannot create an id incorrectly + from brecal_utils.stubs import generate_uuid1_int + ship = get_ship_simple() + ship.is_tug = True + ship.participant_id = str(generate_uuid1_int()) + with pytest.raises(AssertionError): + assert ship_participant_id_is_none_or_int(ship)[0], f"the participant_id should either be None or int, but is str" + return + + +# tug: values must be set, but are not. all tests should raise AssertionError +def test_ship_is_tug_bollard_pull_but_is_none_fails(): + ship = get_ship_simple() + ship.is_tug = True + ship.bollard_pull = None + with pytest.raises(AssertionError): + assert ship_bollard_pull_is_defined_or_is_not_tug(ship)[0], f"the bollard_pull cannot be None, if the ship is a tug" + return + +def test_ship_is_tug_max_draft_but_is_none_fails(): + ship = get_ship_simple() + ship.is_tug = True + ship.max_draft = None + with pytest.raises(AssertionError): + assert ship_max_draft_is_defined_or_is_not_tug(ship)[0], f"the max_draft cannot be None, if the ship is a tug" + return + +def test_ship_is_tug_participant_id_but_is_none_fails(): + ship = get_ship_simple() + ship.is_tug = True + ship.participant_id = None + with pytest.raises(AssertionError): + assert ship_participant_id_is_defined_or_is_not_tug(ship)[0], f"the participant_id cannot be None, if the ship is a tug" + return + + +# tug: values must be in valid range +# # sequence: 1.) is valid, 2.) is too small, 3.) is too large +def test_ship_is_tug_bollard_pull_in_range_311_valid(): + ship = get_ship_simple() + ship.is_tug = True + ship.bollard_pull = 311 + assert ship_bollard_pull_is_none_or_in_range(ship)[0], f"the bollard_pull must be 0