From ef3194b247c80c88b194a5bad6de6c5f3fbd5b08 Mon Sep 17 00:00:00 2001 From: Trishna Saeharaseelan <trishna.saeharaseelan@noc.ac.uk> Date: Thu, 26 Jan 2023 15:51:52 +0800 Subject: [PATCH] refactor(tests): to unittests --- README.md | 26 +-- .../acknowledgement.json | 16 ++ .../mission_plan_ECOSUB.json | 2 +- .../platform_status-from_usbl_example.json | 21 +++ .../platform_status.json | 44 +++++ .../hydrosurv_adapter/platform_status.json | 4 +- tests/test.py | 168 ----------------- tests/test_schemas.py | 178 ++++++++++++++++++ 8 files changed, 277 insertions(+), 182 deletions(-) create mode 100644 examples/autonomy_engine_adapter/acknowledgement.json create mode 100644 examples/autonomy_engine_adapter/platform_status-from_usbl_example.json create mode 100644 examples/autonomy_engine_adapter/platform_status.json delete mode 100644 tests/test.py create mode 100644 tests/test_schemas.py diff --git a/README.md b/README.md index 51a5ed9..61f5e65 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,29 @@ # Overview This project repository is a collaborative workspace. It consists of all messages transferred into and out of the Communications Backbone. Message type schemas will be developed once reviewing each platform's data and statuses defined by each partner. +The schemas are using OpenApi 3.0 (due to the `payload` sub-schemas that vary according to the `message_type`). -_# TODO: Add note on OpenAPI version used._ - -# Message Types -Each message below will be wrapped in a `message_wrapper`: +## Message Types +Each message below will be wrapped in a `payload` field and will have a `header` with message metadata information: * `mission_plan`: these would be two message types, i. encoded (platform-specific serialized message) and ii. parsed, human-readable message. * `platform_status`: these would be two message types, i. encoded (platform-specific serialized message) and ii. parsed, human-readable message. * `observation`: this would be desired scientific data sent by the platform * `acknowledgement`: level of acknowledgment where an acknowledgement is sent when a message is i. received, ii. sent to the next destination (e.g. platform in the water). * `planning_configuration`: sent from the GUI to initialise the AI model (autonomy engine). -# Run Docs -1. Run the command below +## Run Docs +Run the command below and go to `http://127.0.0.1:5000` +``` +python3 generate_schema_config.py +``` +## Run Tests +Run the command below ``` -python3 generate_swagger.py +python3 -m unittest tests/test_schemas.py ``` -2. Go to `http://127.0.0.1:5000` # Quick Links -1. [Schema Fields Definitions](https://git.noc.ac.uk/communications-backbone-system/backbone-message-format/-/tree/7-message-formats-initial/formats) -2. [JSON Schema Examples](https://git.noc.ac.uk/communications-backbone-system/backbone-message-format/-/tree/7-message-formats-initial/examples) -3. Ongoing Project: [SoAR README.md](https://git.noc.ac.uk/communications-backbone-system/backbone-message-format/-/tree/7-message-formats-initial/project/SOAR_README.md) \ No newline at end of file +1. [Generated Swagger Docs (recommended to look at this)](https://git.noc.ac.uk/communications-backbone-system/backbone-message-format/-/blob/dev/project/soar/swagger.json) +2. [Schema Fields Definitions](https://git.noc.ac.uk/communications-backbone-system/backbone-message-format/-/tree/dev/formats) +3. [JSON Schema Examples](https://git.noc.ac.uk/communications-backbone-system/backbone-message-format/-/tree/dev/examples) +4. Ongoing Project: [SoAR README.md](https://git.noc.ac.uk/communications-backbone-system/backbone-message-format/-/blob/dev/project/soar/SOAR_README.md) \ No newline at end of file diff --git a/examples/autonomy_engine_adapter/acknowledgement.json b/examples/autonomy_engine_adapter/acknowledgement.json new file mode 100644 index 0000000..c5290f5 --- /dev/null +++ b/examples/autonomy_engine_adapter/acknowledgement.json @@ -0,0 +1,16 @@ +{ + "header":{ + "message_ID": "b427003c-0000-11aa-a1eb-bvcdfghjgfdd", + "timestamp": "2022-11-16T00:00:00Z", + "version": 1, + "source": "hydrosurv_adapter", + "destination": "autonomy_engine", + "delivery_type": "publish", + "encoded": false + }, + "payload":{ + "message_type": "acknowledgement", + "acknowledged_message_ID": "11111111-7bc8-11ed-a1eb-0242ac999999", + "status": "c2_received" + } +} \ No newline at end of file diff --git a/examples/autonomy_engine_adapter/mission_plan_ECOSUB.json b/examples/autonomy_engine_adapter/mission_plan_ECOSUB.json index f9a136d..d7fd238 100644 --- a/examples/autonomy_engine_adapter/mission_plan_ECOSUB.json +++ b/examples/autonomy_engine_adapter/mission_plan_ECOSUB.json @@ -45,7 +45,7 @@ "flight_style": "go to surface", "latitude_waypoint": -0.237143188645706, "longitude_waypoint": 52.37072283932642, - "depth": 0.0, + "depth": 0, "activate_payload": false, "send_environmental_data": true } diff --git a/examples/autonomy_engine_adapter/platform_status-from_usbl_example.json b/examples/autonomy_engine_adapter/platform_status-from_usbl_example.json new file mode 100644 index 0000000..6721a35 --- /dev/null +++ b/examples/autonomy_engine_adapter/platform_status-from_usbl_example.json @@ -0,0 +1,21 @@ +{ + "header":{ + "message_ID": "b427003c-0000-11aa-a1eb-bvcdfghjgfdd", + "timestamp": "2022-11-16T00:00:00Z", + "version": 2, + "source": "hermes", + "destination": "autonomy_engine", + "delivery_type": "publish", + "encoded": false + }, + "payload":{ + "message_type": "platform_status", + "platform_ID": "ecosub-5", + "platform_timestamp": "2022-12-21T00:00:00Z", + "status_source": "usbl", + "latitude": 178.2, + "longitude": -10.122, + "depth": 50, + "altitude": 20 + } +} diff --git a/examples/autonomy_engine_adapter/platform_status.json b/examples/autonomy_engine_adapter/platform_status.json new file mode 100644 index 0000000..b82beba --- /dev/null +++ b/examples/autonomy_engine_adapter/platform_status.json @@ -0,0 +1,44 @@ +{ + "header":{ + "message_ID": "b427003c-0000-11aa-a1eb-bvcdfghjgfdd", + "timestamp": "2022-11-16T00:00:00Z", + "version": 2, + "source": "ecosub_c2", + "destination": "autonomy_engine", + "delivery_type": "publish", + "encoded": false + }, + "payload":{ + "message_type": "platform_status", + "platform_ID": "ecosub-2", + "platform_timestamp": "2022-12-21T00:00:00Z", + "status_source": "onboard_platform", + "autonomy_engine_plan_ID": 1, + "battery_remaining_capacity": 80.2, + "active": true, + "platform_state": "ABORT", + "mission_action_ID": 1, + "mission_track_ID": 4, + "latitude": 178.2, + "longitude": -10.122, + "depth": 50, + "altitude": 20, + "heading": 90.0, + "health_status": "Warning", + "localisation_error": 0, + "usbl_fix_seconds_ago": 0, + "range_to_go": 124.3, + "sensor_config": { + "sensor_ID": 22, + "serial": "sidescan-2x", + "sensor_on": true, + "additional_data": { + "whiskers_on": true + } + }, + "current_pitch": -4, + "speed_over_ground": 4.3, + "thrust_applied": 124.3, + "water_current_velocity": 124.3 + } +} diff --git a/examples/hydrosurv_adapter/platform_status.json b/examples/hydrosurv_adapter/platform_status.json index cbfb2c6..43bac1f 100644 --- a/examples/hydrosurv_adapter/platform_status.json +++ b/examples/hydrosurv_adapter/platform_status.json @@ -24,7 +24,7 @@ "platform_state": "ABORT", "platform_timestamp": "2022-12-21T00:00:00Z", "speed_over_ground": 4.5, - "range_to_go": null, - "thrust_applied": null + "range_to_go": 0.0, + "thrust_applied": 2.3 } } \ No newline at end of file diff --git a/tests/test.py b/tests/test.py deleted file mode 100644 index 0018211..0000000 --- a/tests/test.py +++ /dev/null @@ -1,168 +0,0 @@ -from openapi_spec_validator import openapi_v30_spec_validator, openapi_v3_spec_validator -from openapi_spec_validator.readers import read_from_filename -from openapi_schema_validator import validate -from jsonschema import FormatChecker -from jsonschema import validate - -from fixtures.schemas import ( - acknowledgement_schema, - message_header, - observation_schema, - planning_configuration_schema, - platform_status_schema, - mission_plan_schema, -) -import json -""" -Test specs -""" -schema, spec_url = read_from_filename("fixtures/swagger.json") -errors_iterator = openapi_v3_spec_validator.iter_errors(schema) -print(errors_iterator) -print(openapi_v30_spec_validator.validate(schema)) - -""" -Test schema - Hydrosurv Messages -""" -message_types = ["acknowledgement", "mission_plan", "platform_status"] -for item in message_types: - f = open("mock_data/hydrosurv_adapter/%s.json" % item) - mock_data = json.load(f) - header_data = mock_data["header"] - payload_data = mock_data["payload"] - print(validate(header_data, message_header, format_checker=FormatChecker())) - if item == "acknowledgement": - print( - validate( - payload_data, acknowledgement_schema, format_checker=FormatChecker() - ) - ) - elif item == "mission_plan": - print( - validate(payload_data, mission_plan_schema, format_checker=FormatChecker()) - ) - elif item == "platform_status": - print( - validate( - payload_data, platform_status_schema, format_checker=FormatChecker() - ) - ) - - -""" -Test schema - GUI Messages -""" -message_types = ["planning_configuration"] -for item in message_types: - f = open("mock_data/gui_adapter/%s.json" % item) - mock_data = json.load(f) - header_data = mock_data["header"] - payload_data = mock_data["payload"] - print(validate(header_data, message_header, format_checker=FormatChecker())) - if item == "planning_configuration": - print( - validate( - payload_data, - planning_configuration_schema, - format_checker=FormatChecker(), - ) - ) - - -""" -Test schema - Ecosub Messages -""" -message_types = [ - "observation", - "mission_plan", - "platform_status", - "platform_status-from_usbl_example", -] -for item in message_types: - f = open("mock_data/ecosub_adapter/%s.json" % item) - mock_data = json.load(f) - header_data = mock_data["header"] - payload_data = mock_data["payload"] - print(validate(header_data, message_header, format_checker=FormatChecker())) - if item == "platform_status-from_usbl_example.json": - print( - validate( - payload_data, platform_status_schema, format_checker=FormatChecker() - ) - ) - elif item == "mission_plan": - print( - validate(payload_data, mission_plan_schema, format_checker=FormatChecker()) - ) - elif item == "platform_status": - print( - validate( - payload_data, platform_status_schema, format_checker=FormatChecker() - ) - ) - elif item == "observation": - print( - validate(payload_data, observation_schema, format_checker=FormatChecker()) - ) - - -""" -Test schema - Autonomy Engine Messages -""" -message_types = [ - "planning_configuration", - "mission_plan_AH1", - "mission_plan_ECOSUB", - "mission_plan_HYDROSURV", - "platform_status", - "platform_status-from_usbl_example", - "acknowledgement", -] -for item in message_types: - f = open("mock_data/autonomy_engine_adapter/%s.json" % item) - mock_data = json.load(f) - header_data = mock_data["header"] - payload_data = mock_data["payload"] - print(validate(header_data, message_header, format_checker=FormatChecker())) - if item == "platform_status-from_usbl_example.json": - print( - validate( - payload_data, platform_status_schema, format_checker=FormatChecker() - ) - ) - elif item == "mission_plan_AH1": - print( - validate(payload_data, mission_plan_schema, format_checker=FormatChecker()) - ) - elif item == "mission_plan_ECOSUB": - print( - validate(payload_data, mission_plan_schema, format_checker=FormatChecker()) - ) - elif item == "mission_plan_HYDROSURV": - print( - validate(payload_data, mission_plan_schema, format_checker=FormatChecker()) - ) - elif item == "platform_status": - print( - validate( - payload_data, platform_status_schema, format_checker=FormatChecker() - ) - ) - elif item == "observation": - print( - validate(payload_data, observation_schema, format_checker=FormatChecker()) - ) - elif item == "planning_configuration": - print( - validate( - payload_data, - planning_configuration_schema, - format_checker=FormatChecker(), - ) - ) - elif item == "acknowledgement": - print( - validate( - payload_data, acknowledgement_schema, format_checker=FormatChecker() - ) - ) diff --git a/tests/test_schemas.py b/tests/test_schemas.py new file mode 100644 index 0000000..a2942e1 --- /dev/null +++ b/tests/test_schemas.py @@ -0,0 +1,178 @@ +from openapi_spec_validator import openapi_v30_spec_validator, openapi_v3_spec_validator +from openapi_spec_validator.readers import read_from_filename +from openapi_schema_validator import validate +from jsonschema import FormatChecker +from jsonschema import validate + +import unittest + +from tests.fixtures.schemas import ( + acknowledgement_schema, + message_header, + observation_schema, + planning_configuration_schema, + platform_status_schema, + mission_plan_schema, +) +import json + + +class TestSpecs(unittest.TestCase): + def test_swagger_specs(self): + """ + Test specs (swagger.json generated from generate_schema_config.py) + """ + schema, spec_url = read_from_filename("tests/fixtures/swagger.json") + self.assertIsNone(openapi_v30_spec_validator.validate(schema)) + + +class TestSchema(unittest.TestCase): + def test_sample_hydrosurv_messages(self): + """ + Test schema - Hydrosurv Messages + """ + message_types = ["acknowledgement", "mission_plan", "platform_status"] + for item in message_types: + f = open("examples/hydrosurv_adapter/%s.json" % item) + mock_data = json.load(f) + header_data = mock_data["header"] + payload_data = mock_data["payload"] + self.assertIsNone(validate(header_data, message_header, format_checker=FormatChecker())) + if item == "acknowledgement": + self.assertIsNone( + validate( + payload_data, acknowledgement_schema, format_checker=FormatChecker() + ) + ) + elif item == "mission_plan": + self.assertIsNone( + validate(payload_data, mission_plan_schema, format_checker=FormatChecker()) + ) + elif item == "platform_status": + self.assertIsNone( + validate( + payload_data, platform_status_schema, format_checker=FormatChecker() + ) + ) + + def test_sample_gui_messages(self): + """ + Test schema - GUI Messages + """ + message_types = ["planning_configuration"] + for item in message_types: + f = open("examples/gui_adapter/%s.json" % item) + mock_data = json.load(f) + header_data = mock_data["header"] + payload_data = mock_data["payload"] + self.assertIsNone(validate(header_data, message_header, format_checker=FormatChecker())) + if item == "planning_configuration": + self.assertIsNone( + validate( + payload_data, + planning_configuration_schema, + format_checker=FormatChecker(), + ) + ) + + def test_sample_ecosub_messages(self): + """ + Test schema - Ecosub Messages + """ + message_types = [ + "observation", + "mission_plan", + "platform_status", + "platform_status-from_usbl_example", + ] + for item in message_types: + f = open("examples/ecosub_adapter/%s.json" % item) + mock_data = json.load(f) + header_data = mock_data["header"] + payload_data = mock_data["payload"] + self.assertIsNone(validate(header_data, message_header, format_checker=FormatChecker())) + if item == "platform_status-from_usbl_example.json": + self.assertIsNone( + validate( + payload_data, platform_status_schema, format_checker=FormatChecker() + ) + ) + elif item == "mission_plan": + self.assertIsNone( + validate(payload_data, mission_plan_schema, format_checker=FormatChecker()) + ) + elif item == "platform_status": + self.assertIsNone( + validate( + payload_data, platform_status_schema, format_checker=FormatChecker() + ) + ) + elif item == "observation": + self.assertIsNone( + validate(payload_data, observation_schema, format_checker=FormatChecker()) + ) + + def test_sample_autonomy_engine_messages(self): + """ + Test schema - Autonomy Engine Messages + """ + message_types = [ + "planning_configuration", + "mission_plan_AH1", + "mission_plan_ECOSUB", + "mission_plan_HYDROSURV", + "platform_status", + "platform_status-from_usbl_example", + "acknowledgement", + ] + for item in message_types: + f = open("examples/autonomy_engine_adapter/%s.json" % item) + mock_data = json.load(f) + header_data = mock_data["header"] + payload_data = mock_data["payload"] + self.assertIsNone(validate(header_data, message_header, format_checker=FormatChecker())) + if item == "platform_status-from_usbl_example.json": + self.assertIsNone( + validate( + payload_data, platform_status_schema, format_checker=FormatChecker() + ) + ) + elif item == "mission_plan_AH1": + self.assertIsNone( + validate(payload_data, mission_plan_schema, format_checker=FormatChecker()) + ) + elif item == "mission_plan_ECOSUB": + self.assertIsNone( + validate(payload_data, mission_plan_schema, format_checker=FormatChecker()) + ) + elif item == "mission_plan_HYDROSURV": + self.assertIsNone( + validate(payload_data, mission_plan_schema, format_checker=FormatChecker()) + ) + elif item == "platform_status": + self.assertIsNone( + validate( + payload_data, platform_status_schema, format_checker=FormatChecker() + ) + ) + elif item == "observation": + self.assertIsNone( + validate(payload_data, observation_schema, format_checker=FormatChecker()) + ) + elif item == "planning_configuration": + self.assertIsNone( + validate( + payload_data, + planning_configuration_schema, + format_checker=FormatChecker(), + ) + ) + elif item == "acknowledgement": + self.assertIsNone( + validate( + payload_data, acknowledgement_schema, format_checker=FormatChecker() + ) + ) + +if __name__ == '__main__': + unittest.main() -- GitLab