updating validators, time handling, creating tests for time & schemas. Decoupling schema validation according to the dataclasses. Starting to stub & create notifications
This commit is contained in:
parent
4195655e4e
commit
3edc6d86ba
1
.gitignore
vendored
1
.gitignore
vendored
@ -442,4 +442,5 @@ src/notebooks_metz
|
||||
docs/traffic_light_examples
|
||||
**/.~lock*
|
||||
misc/berths_and_terminals.csv
|
||||
times.md
|
||||
|
||||
|
||||
@ -37,6 +37,8 @@ dependencies:
|
||||
- conda-forge::cached_property>=1.5.2=pyha770c72_1
|
||||
- conda-forge::dsnparse>=0.2.1=pyhd8ed1ab_0
|
||||
|
||||
- conda-forge::schedule>=1.2.0=pyhd8ed1ab_0
|
||||
|
||||
- pip:
|
||||
# pip packages and wheels
|
||||
- pyjwt==2.7.0
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
from ._version import __version__
|
||||
from brecal_utils.file_handling import get_project_root, ensure_path
|
||||
from brecal_utils.test_handling import execute_test_with_pytest, execute_coverage_test
|
||||
from brecal_utils.time_handling import difference_to_then
|
||||
|
||||
from brecal_utils.validators.time_logic import TimeLogic
|
||||
from brecal_utils.validators.validation_rules import ValidationRules
|
||||
from brecal_utils.validators.schema_validation import validation_state_and_validation_name
|
||||
@ -10,6 +12,7 @@ __all__ = [
|
||||
"ensure_path",
|
||||
"execute_test_with_pytest",
|
||||
"execute_coverage_test",
|
||||
"difference_to_then",
|
||||
"TimeLogic",
|
||||
"ValidationRules",
|
||||
"validation_state_and_validation_name",
|
||||
|
||||
49
src/lib_brecal_utils/brecal_utils/stubs/notification.py
Normal file
49
src/lib_brecal_utils/brecal_utils/stubs/notification.py
Normal file
@ -0,0 +1,49 @@
|
||||
import datetime
|
||||
from brecal_utils.stubs import generate_uuid1_int
|
||||
from BreCal.schemas.model import Notification
|
||||
|
||||
|
||||
def get_notification_simple():
|
||||
"""creates a default notification, where 'created' is now, and modified is now+10 seconds"""
|
||||
notification_id = generate_uuid1_int() # uid?
|
||||
times_id = generate_uuid1_int() # uid?
|
||||
acknowledged = False
|
||||
level = 10
|
||||
type = 0
|
||||
message = "hello world"
|
||||
created = datetime.datetime.now()
|
||||
modified = created+datetime.timedelta(seconds=10)
|
||||
|
||||
notification = Notification(
|
||||
notification_id,
|
||||
times_id,
|
||||
acknowledged,
|
||||
level,
|
||||
type,
|
||||
message,
|
||||
created,
|
||||
modified
|
||||
)
|
||||
return notification
|
||||
|
||||
def get_notification_in_the_past(created_delta_seconds, modified_delta_seconds, acknowledged=False):
|
||||
"""
|
||||
creates a notification of the past, where the
|
||||
'created' date is {created_delta_seconds} seconds ago
|
||||
'modified' date is {modified_delta_seconds} seconds ago
|
||||
|
||||
for example, if datetime.datetime.now() returns
|
||||
now = datetime.datetime(2023, 9, 15, 7, 25, 50, 733644)), then calling this function
|
||||
as get_notification_modified_in_the_past(2*60, 1*60) provides
|
||||
'created':datetime.datetime(2023, 9, 15, 7, 23, 50, 733644) (two minutes ago)
|
||||
'modified':datetime.datetime(2023, 9, 15, 7, 24, 50, 733644) (one minute ago)
|
||||
|
||||
optionally, one can also overwrite the 'acknowledged' attribute
|
||||
returns notification
|
||||
"""
|
||||
notification = get_notification_simple()
|
||||
notification.created = datetime.datetime.now()-datetime.timedelta(seconds=created_delta_seconds)
|
||||
notification.modified = datetime.datetime.now()-datetime.timedelta(seconds=modified_delta_seconds)
|
||||
notification.acknowledged = acknowledged
|
||||
return notification
|
||||
|
||||
21
src/lib_brecal_utils/brecal_utils/time_handling.py
Normal file
21
src/lib_brecal_utils/brecal_utils/time_handling.py
Normal file
@ -0,0 +1,21 @@
|
||||
import datetime
|
||||
|
||||
def difference_to_then(event_time, tgt_time=None, make_absolute=False):
|
||||
"""
|
||||
measures the difference between {tgt_time} and {event_time}. this function automatically converts the datetime.timedelta object to seconds.
|
||||
tgt_time defaults to {now}, if it is not specified.
|
||||
|
||||
Note: using divmod(time_diff, interval_duration) may be interesting to determine, how many units of {interval_duration} have passed.
|
||||
e.g.,
|
||||
divmod(time_diff, 3600) returns a float of hours. This will then return a tuple
|
||||
|
||||
options:
|
||||
make_absolute: bool. Whether to return an absolute difference
|
||||
|
||||
Returns: time_diff (float)
|
||||
"""
|
||||
tgt_time = tgt_time or datetime.datetime.now()
|
||||
time_diff = tgt_time - event_time
|
||||
if make_absolute:
|
||||
return abs(time_diff.total_seconds())
|
||||
return time_diff.total_seconds()
|
||||
@ -51,6 +51,12 @@ def test_build_stub_times():
|
||||
assert isinstance(times, Times)
|
||||
return
|
||||
|
||||
def test_build_stub_notification():
|
||||
from BreCal.schemas.model import Notification
|
||||
from brecal_utils.stubs.notification import get_notification_simple
|
||||
notification = get_notification_simple()
|
||||
assert isinstance(notification, Notification)
|
||||
|
||||
if __name__=="__main__":
|
||||
test_build_stub_berth()
|
||||
test_build_stub_participant()
|
||||
@ -60,3 +66,4 @@ if __name__=="__main__":
|
||||
test_build_stub_tug()
|
||||
test_build_stub_shipcall()
|
||||
test_build_stub_times()
|
||||
test_build_stub_notification()
|
||||
|
||||
@ -79,6 +79,19 @@ def test_import_bcrypt():
|
||||
import bcrypt
|
||||
return
|
||||
|
||||
def test_import_math():
|
||||
"""math.isclose can be interesting to measure differences between two times (e.g., to ignore milliseconds)"""
|
||||
import math
|
||||
math.isclose
|
||||
return
|
||||
|
||||
def test_import_datetime():
|
||||
"""datetime is the default library for times"""
|
||||
import datetime
|
||||
datetime.datetime.now()
|
||||
return
|
||||
|
||||
|
||||
if __name__=="__main__":
|
||||
test_import_colorama()
|
||||
test_import_matplotlib()
|
||||
|
||||
50
src/lib_brecal_utils/tests/test_time_handling.py
Normal file
50
src/lib_brecal_utils/tests/test_time_handling.py
Normal file
@ -0,0 +1,50 @@
|
||||
import pytest
|
||||
|
||||
def test_difference_to_then_tgt_time_none():
|
||||
import math
|
||||
import datetime
|
||||
from brecal_utils import difference_to_then
|
||||
|
||||
difference_in_seconds = 42
|
||||
event_time = datetime.datetime.now() - datetime.timedelta(seconds=difference_in_seconds)
|
||||
event_time_diff = difference_to_then(event_time) # tgt_time = datetime.datetime.now()
|
||||
|
||||
# {difference_to_then} internally creates a .now() time, when the {then_time} is not defined
|
||||
# hence, the difference will never be exactly 42 seconds due to slight latency
|
||||
# math.isclose allows deviations up to 0.05 seconds
|
||||
assert math.isclose(42, event_time_diff, abs_tol=0.05), f"both times are reasonably close"
|
||||
return
|
||||
|
||||
def test_difference_to_then_tgt_time_not_none():
|
||||
import math
|
||||
import datetime
|
||||
from brecal_utils import difference_to_then
|
||||
|
||||
difference_in_seconds = 42
|
||||
event_time = datetime.datetime(2000, 1, 1, 0, 0, 0)
|
||||
tgt_time = event_time - datetime.timedelta(seconds=difference_in_seconds)
|
||||
event_time_diff = difference_to_then(event_time, tgt_time)
|
||||
|
||||
# tgt time is -42 seconds, as it is 42 seconds before event_time
|
||||
assert event_time_diff==-42, f"event time difference is incorrect"
|
||||
return
|
||||
|
||||
def test_difference_to_then_tgt_time_not_none_make_absolute():
|
||||
import math
|
||||
import datetime
|
||||
from brecal_utils import difference_to_then
|
||||
|
||||
difference_in_seconds = 42
|
||||
event_time = datetime.datetime(2000, 1, 1, 0, 0, 0)
|
||||
tgt_time = event_time - datetime.timedelta(seconds=difference_in_seconds)
|
||||
event_time_diff = difference_to_then(event_time, tgt_time, make_absolute=True) # difference: -42. make_absolute: +42
|
||||
|
||||
# tgt time is -42 seconds, as it is 42 seconds before event_time. However, we are interested in an absolute value
|
||||
assert event_time_diff==42, f"event time difference is incorrect"
|
||||
return
|
||||
|
||||
|
||||
if __name__=="__main__":
|
||||
test_difference_to_then()
|
||||
|
||||
|
||||
@ -0,0 +1,12 @@
|
||||
import pytest
|
||||
from brecal_utils.stubs.berth import get_berth_simple
|
||||
|
||||
def test_berth():
|
||||
berth = get_berth_simple()
|
||||
raise ValueError("copied from ships.")
|
||||
from brecal_utils.validators.schema_validation import test____
|
||||
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
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
import pytest
|
||||
from brecal_utils.stubs.participant import get_participant_simple
|
||||
|
||||
def test_participant_postal_code_len_is_five():
|
||||
from brecal_utils.validators.schema_validation import participant_postal_code_len_is_five
|
||||
|
||||
participant = get_participant_simple()
|
||||
assert participant_postal_code_len_is_five(participant)[0], f"the postal code should be exactly 5 numbers"
|
||||
return
|
||||
|
||||
def test_participant_postal_code_len_is_six_should_assert():
|
||||
from brecal_utils.validators.schema_validation import participant_postal_code_len_is_five
|
||||
|
||||
participant = get_participant_simple()
|
||||
participant.postal_code = "123456"
|
||||
with pytest.raises(AssertionError, match="the postal code should be exactly 5 numbers"):
|
||||
assert participant_postal_code_len_is_five(participant)[0], f"the postal code should be exactly 5 numbers"
|
||||
return
|
||||
|
||||
# TODO_postal_code_zero -> assert? Is postal_code mandatory?
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__=="__main__":
|
||||
test_participant_postal_code_len_is_five()
|
||||
test_participant_postal_code_len_is_six_should_assert()
|
||||
|
||||
@ -1,14 +1,15 @@
|
||||
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():
|
||||
from brecal_utils.validators.schema_validation import ship_length_in_range
|
||||
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():
|
||||
from brecal_utils.validators.schema_validation import ship_length_in_range
|
||||
ship = get_ship_simple()
|
||||
ship.length = 500
|
||||
with pytest.raises(AssertionError):
|
||||
@ -16,6 +17,7 @@ def test_ship_length_maximum_not_valid_range():
|
||||
return
|
||||
|
||||
def test_ship_length_minimum_not_valid_range():
|
||||
from brecal_utils.validators.schema_validation import ship_length_in_range
|
||||
ship = get_ship_simple()
|
||||
ship.length = 0
|
||||
with pytest.raises(AssertionError):
|
||||
@ -23,12 +25,14 @@ def test_ship_length_minimum_not_valid_range():
|
||||
return
|
||||
|
||||
def test_ship_width_valid_range_137_is_valid():
|
||||
from brecal_utils.validators.schema_validation import ship_width_in_range
|
||||
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():
|
||||
from brecal_utils.validators.schema_validation import ship_width_in_range
|
||||
ship = get_ship_simple()
|
||||
ship.width = 500
|
||||
with pytest.raises(AssertionError):
|
||||
@ -36,6 +40,7 @@ def test_ship_width_maximum_not_valid_range():
|
||||
return
|
||||
|
||||
def test_ship_width_minimum_not_valid_range():
|
||||
from brecal_utils.validators.schema_validation import ship_width_in_range
|
||||
ship = get_ship_simple()
|
||||
ship.width = 0
|
||||
with pytest.raises(AssertionError):
|
||||
@ -44,6 +49,7 @@ def test_ship_width_minimum_not_valid_range():
|
||||
|
||||
# not tug: values can be None and raise no error
|
||||
def test_ship_bollard_pull_is_none_and_not_tug():
|
||||
from brecal_utils.validators.schema_validation import ship_bollard_pull_is_none_or_in_range
|
||||
ship = get_ship_simple()
|
||||
ship.is_tug = False
|
||||
ship.bollard_pull = None
|
||||
@ -51,6 +57,7 @@ def test_ship_bollard_pull_is_none_and_not_tug():
|
||||
return
|
||||
|
||||
def test_ship_participant_id_is_none_and_not_tug():
|
||||
from brecal_utils.validators.schema_validation import ship_participant_id_is_none_or_int
|
||||
ship = get_ship_simple()
|
||||
ship.is_tug = False
|
||||
ship.participant_id = None
|
||||
@ -58,6 +65,7 @@ def test_ship_participant_id_is_none_and_not_tug():
|
||||
return
|
||||
|
||||
def test_ship_max_draft_is_none_and_not_tug():
|
||||
from brecal_utils.validators.schema_validation import ship_max_draft_is_none_or_in_range
|
||||
ship = get_ship_simple()
|
||||
ship.is_tug = False
|
||||
ship.max_draft = None
|
||||
@ -67,6 +75,7 @@ def test_ship_max_draft_is_none_and_not_tug():
|
||||
|
||||
# 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():
|
||||
from brecal_utils.validators.schema_validation import ship_bollard_pull_is_none_or_in_range
|
||||
ship = get_ship_simple()
|
||||
ship.is_tug = True
|
||||
ship.bollard_pull = 311
|
||||
@ -75,6 +84,7 @@ def test_ship_is_tug_bollard_pull_is_not_none():
|
||||
|
||||
|
||||
def test_ship_is_tug_max_draft_is_not_none():
|
||||
from brecal_utils.validators.schema_validation import ship_max_draft_is_none_or_in_range
|
||||
ship = get_ship_simple()
|
||||
ship.is_tug = True
|
||||
ship.max_draft = 17
|
||||
@ -82,6 +92,7 @@ def test_ship_is_tug_max_draft_is_not_none():
|
||||
return
|
||||
|
||||
def test_ship_is_tug_participant_id_is_not_none():
|
||||
from brecal_utils.validators.schema_validation import ship_participant_id_is_none_or_int
|
||||
from brecal_utils.stubs import generate_uuid1_int
|
||||
ship = get_ship_simple()
|
||||
ship.is_tug = True
|
||||
@ -90,6 +101,7 @@ def test_ship_is_tug_participant_id_is_not_none():
|
||||
return
|
||||
|
||||
def test_ship_is_tug_participant_id_is_str_and_fails():
|
||||
from brecal_utils.validators.schema_validation import ship_participant_id_is_none_or_int
|
||||
# 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()
|
||||
@ -102,6 +114,7 @@ def test_ship_is_tug_participant_id_is_str_and_fails():
|
||||
|
||||
# tug: values must be set, but are not. all tests should raise AssertionError
|
||||
def test_ship_is_tug_bollard_pull_but_is_none_fails():
|
||||
from brecal_utils.validators.schema_validation import ship_bollard_pull_is_defined_or_is_not_tug
|
||||
ship = get_ship_simple()
|
||||
ship.is_tug = True
|
||||
ship.bollard_pull = None
|
||||
@ -110,6 +123,7 @@ def test_ship_is_tug_bollard_pull_but_is_none_fails():
|
||||
return
|
||||
|
||||
def test_ship_is_tug_max_draft_but_is_none_fails():
|
||||
from brecal_utils.validators.schema_validation import ship_max_draft_is_defined_or_is_not_tug
|
||||
ship = get_ship_simple()
|
||||
ship.is_tug = True
|
||||
ship.max_draft = None
|
||||
@ -118,6 +132,7 @@ def test_ship_is_tug_max_draft_but_is_none_fails():
|
||||
return
|
||||
|
||||
def test_ship_is_tug_participant_id_but_is_none_fails():
|
||||
from brecal_utils.validators.schema_validation import ship_participant_id_is_defined_or_is_not_tug
|
||||
ship = get_ship_simple()
|
||||
ship.is_tug = True
|
||||
ship.participant_id = None
|
||||
@ -129,6 +144,7 @@ def test_ship_is_tug_participant_id_but_is_none_fails():
|
||||
# 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():
|
||||
from brecal_utils.validators.schema_validation import ship_bollard_pull_is_none_or_in_range
|
||||
ship = get_ship_simple()
|
||||
ship.is_tug = True
|
||||
ship.bollard_pull = 311
|
||||
@ -136,6 +152,7 @@ def test_ship_is_tug_bollard_pull_in_range_311_valid():
|
||||
return
|
||||
|
||||
def test_ship_is_tug_bollard_pull_in_range_minimum_not_valid():
|
||||
from brecal_utils.validators.schema_validation import ship_bollard_pull_is_none_or_in_range
|
||||
ship = get_ship_simple()
|
||||
ship.is_tug = True
|
||||
ship.bollard_pull = 0
|
||||
@ -144,6 +161,7 @@ def test_ship_is_tug_bollard_pull_in_range_minimum_not_valid():
|
||||
return
|
||||
|
||||
def test_ship_is_tug_bollard_pull_in_range_maximum_not_valid():
|
||||
from brecal_utils.validators.schema_validation import ship_bollard_pull_is_none_or_in_range
|
||||
ship = get_ship_simple()
|
||||
ship.is_tug = True
|
||||
ship.bollard_pull = 500
|
||||
@ -152,6 +170,7 @@ def test_ship_is_tug_bollard_pull_in_range_maximum_not_valid():
|
||||
return
|
||||
|
||||
def test_ship_is_tug_max_draft_in_range_11_valid():
|
||||
from brecal_utils.validators.schema_validation import ship_max_draft_is_none_or_in_range
|
||||
ship = get_ship_simple()
|
||||
ship.is_tug = True
|
||||
ship.max_draft = 11
|
||||
@ -159,6 +178,7 @@ def test_ship_is_tug_max_draft_in_range_11_valid():
|
||||
return
|
||||
|
||||
def test_ship_is_tug_max_draft_in_range_minimum_not_valid():
|
||||
from brecal_utils.validators.schema_validation import ship_max_draft_is_none_or_in_range
|
||||
ship = get_ship_simple()
|
||||
ship.is_tug = True
|
||||
ship.max_draft = 0
|
||||
@ -167,6 +187,7 @@ def test_ship_is_tug_max_draft_in_range_minimum_not_valid():
|
||||
return
|
||||
|
||||
def test_ship_is_tug_max_draft_in_range_maximum_not_valid():
|
||||
from brecal_utils.validators.schema_validation import ship_max_draft_is_none_or_in_range
|
||||
ship = get_ship_simple()
|
||||
ship.is_tug = True
|
||||
ship.max_draft = 20
|
||||
@ -177,12 +198,14 @@ def test_ship_is_tug_max_draft_in_range_maximum_not_valid():
|
||||
# Length tests
|
||||
|
||||
def test_ship_eni_len_is_eight_and_passes():
|
||||
from brecal_utils.validators.schema_validation import ship_eni_len_is_eight
|
||||
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():
|
||||
from brecal_utils.validators.schema_validation import ship_eni_len_is_eight
|
||||
ship = get_ship_simple()
|
||||
ship.eni = "012345678" # 9 character example
|
||||
with pytest.raises(AssertionError):
|
||||
@ -190,18 +213,21 @@ def test_ship_eni_len_is_eight_but_has_nine():
|
||||
return
|
||||
|
||||
def test_ship_callsign_len_is_seven_at_maximum_seven_passes():
|
||||
from brecal_utils.validators.schema_validation import ship_callsign_len_is_seven_at_maximum
|
||||
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():
|
||||
from brecal_utils.validators.schema_validation import ship_callsign_len_is_seven_at_maximum
|
||||
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():
|
||||
from brecal_utils.validators.schema_validation import ship_callsign_len_is_seven_at_maximum
|
||||
ship = get_ship_simple()
|
||||
ship.callsign = "01234567" # 8 character example
|
||||
|
||||
@ -210,18 +236,21 @@ def test_ship_callsign_len_is_seven_at_maximum_eight_fails():
|
||||
return
|
||||
|
||||
def test_ship_callsign_len_is_seven_at_maximum_zero_passes():
|
||||
from brecal_utils.validators.schema_validation import ship_callsign_len_is_seven_at_maximum
|
||||
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():
|
||||
from brecal_utils.validators.schema_validation import ship_imo_len_is_seven
|
||||
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():
|
||||
from brecal_utils.validators.schema_validation import ship_imo_len_is_seven
|
||||
ship = get_ship_simple()
|
||||
ship.imo = 12345678 # integer required
|
||||
with pytest.raises(AssertionError):
|
||||
@ -229,6 +258,7 @@ def test_imo_len_is_seven_and_eight_fails():
|
||||
return
|
||||
|
||||
def test_imo_len_is_seven_and_one_fails():
|
||||
from brecal_utils.validators.schema_validation import ship_imo_len_is_seven
|
||||
ship = get_ship_simple()
|
||||
ship.imo = 1 # integer required
|
||||
with pytest.raises(AssertionError):
|
||||
Reference in New Issue
Block a user