creating unit tests for schema_validation (mostly focusing on the Ship dataclass, as it has the most validation requirement)
This commit is contained in:
parent
20f860586f
commit
4195655e4e
@ -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"""
|
||||
|
||||
0
src/lib_brecal_utils/tests/validators/__init__.py
Normal file
0
src/lib_brecal_utils/tests/validators/__init__.py
Normal file
240
src/lib_brecal_utils/tests/validators/test_schema_validation.py
Normal file
240
src/lib_brecal_utils/tests/validators/test_schema_validation.py
Normal file
@ -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<value<500"
|
||||
return
|
||||
|
||||
def test_ship_is_tug_bollard_pull_in_range_minimum_not_valid():
|
||||
ship = get_ship_simple()
|
||||
ship.is_tug = True
|
||||
ship.bollard_pull = 0
|
||||
with pytest.raises(AssertionError):
|
||||
assert ship_bollard_pull_is_none_or_in_range(ship)[0], f"the bollard_pull must be 0<value<500, but is 0"
|
||||
return
|
||||
|
||||
def test_ship_is_tug_bollard_pull_in_range_maximum_not_valid():
|
||||
ship = get_ship_simple()
|
||||
ship.is_tug = True
|
||||
ship.bollard_pull = 500
|
||||
with pytest.raises(AssertionError):
|
||||
assert ship_bollard_pull_is_none_or_in_range(ship)[0], f"the bollard_pull must be 0<value<500, but is 500"
|
||||
return
|
||||
|
||||
def test_ship_is_tug_max_draft_in_range_11_valid():
|
||||
ship = get_ship_simple()
|
||||
ship.is_tug = True
|
||||
ship.max_draft = 11
|
||||
assert ship_max_draft_is_none_or_in_range(ship)[0], f"the max_draft must be 0<value<20"
|
||||
return
|
||||
|
||||
def test_ship_is_tug_max_draft_in_range_minimum_not_valid():
|
||||
ship = get_ship_simple()
|
||||
ship.is_tug = True
|
||||
ship.max_draft = 0
|
||||
with pytest.raises(AssertionError):
|
||||
assert ship_max_draft_is_none_or_in_range(ship)[0], f"the max_draft must be 0<value<20, but is 0"
|
||||
return
|
||||
|
||||
def test_ship_is_tug_max_draft_in_range_maximum_not_valid():
|
||||
ship = get_ship_simple()
|
||||
ship.is_tug = True
|
||||
ship.max_draft = 20
|
||||
with pytest.raises(AssertionError):
|
||||
assert ship_max_draft_is_none_or_in_range(ship)[0], f"the max_draft must be 0<value<20, but is 20"
|
||||
return
|
||||
|
||||
# Length tests
|
||||
|
||||
def test_ship_eni_len_is_eight_and_passes():
|
||||
ship = get_ship_simple()
|
||||
ship.eni = "01234567" # 8 character example
|
||||
assert ship_eni_len_is_eight(ship)[0], f"the eni-no. should have exactly 8 characters"
|
||||
return
|
||||
|
||||
def test_ship_eni_len_is_eight_but_has_nine():
|
||||
ship = get_ship_simple()
|
||||
ship.eni = "012345678" # 9 character example
|
||||
with pytest.raises(AssertionError):
|
||||
assert ship_eni_len_is_eight(ship)[0], f"the eni-no. should have exactly 8 characters, but has 9 characters"
|
||||
return
|
||||
|
||||
def test_ship_callsign_len_is_seven_at_maximum_seven_passes():
|
||||
ship = get_ship_simple()
|
||||
ship.callsign = "0123456" # 7 character example
|
||||
assert ship_callsign_len_is_seven_at_maximum(ship)[0], f"the callsign no. should have at maximum 7 characters"
|
||||
return
|
||||
|
||||
def test_ship_callsign_len_is_seven_at_maximum_six_passes():
|
||||
ship = get_ship_simple()
|
||||
ship.callsign = "012345" # 6 character example
|
||||
assert ship_callsign_len_is_seven_at_maximum(ship)[0], f"the callsign no. should have at maximum 7 characters"
|
||||
return
|
||||
|
||||
def test_ship_callsign_len_is_seven_at_maximum_eight_fails():
|
||||
ship = get_ship_simple()
|
||||
ship.callsign = "01234567" # 8 character example
|
||||
|
||||
with pytest.raises(AssertionError):
|
||||
assert ship_callsign_len_is_seven_at_maximum(ship)[0], f"the callsign no. should have at maximum 7 characters, but has 8"
|
||||
return
|
||||
|
||||
def test_ship_callsign_len_is_seven_at_maximum_zero_passes():
|
||||
ship = get_ship_simple()
|
||||
ship.callsign = "" # 0 character example
|
||||
assert ship_callsign_len_is_seven_at_maximum(ship)[0], f"the callsign no. should have at maximum 7 characters"
|
||||
return
|
||||
|
||||
def test_imo_len_is_seven_and_seven_passes():
|
||||
ship = get_ship_simple()
|
||||
ship.imo = 1234567 # integer required
|
||||
assert ship_imo_len_is_seven(ship)[0], f"a ship's IMO no. should have exactly 7 characters"
|
||||
return
|
||||
|
||||
def test_imo_len_is_seven_and_eight_fails():
|
||||
ship = get_ship_simple()
|
||||
ship.imo = 12345678 # integer required
|
||||
with pytest.raises(AssertionError):
|
||||
assert ship_imo_len_is_seven(ship)[0], f"a ship's IMO no. should have exactly 7 characters, but it has 8 character"
|
||||
return
|
||||
|
||||
def test_imo_len_is_seven_and_one_fails():
|
||||
ship = get_ship_simple()
|
||||
ship.imo = 1 # integer required
|
||||
with pytest.raises(AssertionError):
|
||||
assert ship_imo_len_is_seven(ship)[0], f"a ship's IMO no. should have exactly 7 characters, but is has 1 character"
|
||||
return
|
||||
|
||||
|
||||
if __name__=="__main__":
|
||||
pass
|
||||
Reference in New Issue
Block a user