Skip to content

Commit a5e477d

Browse files
committed
test(vehicle_components): Added tests for the functionality
1 parent 3ccc385 commit a5e477d

8 files changed

Lines changed: 213 additions & 118 deletions

tests/acceptance_template_import_from_params.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -730,8 +730,8 @@ def get_inferable_fields() -> list[tuple[str, str, str]]:
730730
("Battery", "Specifications", "Capacity mAh"),
731731
("Battery Monitor", "FC Connection", "Type"),
732732
("Battery Monitor", "FC Connection", "Protocol"),
733-
("ESC", "FC Connection", "Type"),
734-
("ESC", "FC Connection", "Protocol"),
733+
("ESC", "FC->ESC Connection", "Type"),
734+
("ESC", "FC->ESC Connection", "Protocol"),
735735
("GNSS Receiver", "FC Connection", "Type"),
736736
("GNSS Receiver", "FC Connection", "Protocol"),
737737
("RC Receiver", "FC Connection", "Type"),

tests/test_data_model_vehicle_components_base.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,36 @@ def test_system_recreates_missing_battery_component(self, realistic_model) -> No
606606
assert "Battery" in realistic_model._data["Components"]
607607
assert "Specifications" in realistic_model._data["Components"]["Battery"]
608608

609+
def test_system_migrates_legacy_esc_fc_connection_path(self) -> None:
610+
"""
611+
System migrates legacy ESC FC Connection to FC->ESC Connection when loading old files.
612+
613+
GIVEN: A model with old ESC path data
614+
WHEN: update_json_structure is called
615+
THEN: ESC data is moved to the new FC->ESC Connection path and old path removed
616+
"""
617+
initial_data = {
618+
"Components": {
619+
"ESC": {
620+
"Product": {"Manufacturer": "Test"},
621+
"FC Connection": {"Type": "Main Out", "Protocol": "DShot600"},
622+
}
623+
},
624+
"Format version": 1,
625+
}
626+
627+
vehicle_components = VehicleComponents()
628+
schema = VehicleComponentsJsonSchema(vehicle_components.load_schema())
629+
component_datatypes = schema.get_all_value_datatypes()
630+
model = ComponentDataModelBase(initial_data, component_datatypes, schema)
631+
632+
model.update_json_structure()
633+
634+
assert "FC Connection" not in model._data["Components"]["ESC"]
635+
assert "FC->ESC Connection" in model._data["Components"]["ESC"]
636+
assert model._data["Components"]["ESC"]["FC->ESC Connection"]["Type"] == "Main Out"
637+
assert model._data["Components"]["ESC"]["FC->ESC Connection"]["Protocol"] == "DShot600"
638+
609639
def test_system_recreates_missing_flight_controller_specifications(self, realistic_model) -> None:
610640
"""
611641
System recreates missing Flight Controller Specifications sub-section.
@@ -882,7 +912,7 @@ def test_system_handles_sequential_access_to_different_components(self, basic_mo
882912
(("Battery", "Specifications", "Capacity mAh"), 2000),
883913
(("Frame", "Specifications", "Weight Kg"), 1.5),
884914
(("Flight Controller", "Product", "Manufacturer"), "TestCorp"),
885-
(("ESC", "FC Connection", "Protocol"), "DShot600"),
915+
(("ESC", "FC->ESC Connection", "Protocol"), "DShot600"),
886916
(("Motors", "Specifications", "Poles"), 14),
887917
]
888918

tests/test_data_model_vehicle_components_import.py

Lines changed: 85 additions & 51 deletions
Large diffs are not rendered by default.

tests/test_data_model_vehicle_components_validation.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -704,8 +704,8 @@ def test_validate_all_data_valid_entries(self, realistic_model) -> None:
704704
("RC Receiver", "FC Connection", "Protocol"): "CRSF",
705705
("GNSS Receiver", "FC Connection", "Type"): "SERIAL3",
706706
("GNSS Receiver", "FC Connection", "Protocol"): "uBlox",
707-
("ESC", "FC Connection", "Type"): "Main Out",
708-
("ESC", "FC Connection", "Protocol"): "DShot600",
707+
("ESC", "FC->ESC Connection", "Type"): "Main Out",
708+
("ESC", "FC->ESC Connection", "Protocol"): "DShot600",
709709
}
710710

711711
is_valid, errors = model.validate_all_data(valid_entries)
@@ -818,7 +818,7 @@ def test_validate_all_data_battery_esc_combinations(self, realistic_model) -> No
818818
allowed_entries = {
819819
("Battery Monitor", "FC Connection", "Type"): "other",
820820
("Battery Monitor", "FC Connection", "Protocol"): "ESC",
821-
("ESC", "FC Connection", "Type"): "Main Out",
821+
("ESC", "FC->ESC Connection", "Type"): "Main Out",
822822
}
823823

824824
is_valid, errors = model.validate_all_data(allowed_entries)
@@ -1311,8 +1311,8 @@ def test_pwm_output_protocol_choices(self, realistic_model) -> None:
13111311
model.init_possible_choices({"MOT_PWM_TYPE": {"values": {"0": "Normal", "6": "DShot600"}}})
13121312

13131313
# Test ESC connection to PWM outputs (not serial or CAN)
1314-
model._update_possible_choices_for_path(("ESC", "FC Connection", "Type"), "Main Out")
1315-
protocol_choices = model._possible_choices.get(("ESC", "FC Connection", "Protocol"), ())
1314+
model._update_possible_choices_for_path(("ESC", "FC->ESC Connection", "Type"), "Main Out")
1315+
protocol_choices = model._possible_choices.get(("ESC", "FC->ESC Connection", "Protocol"), ())
13161316

13171317
# Should use motor PWM types for PWM outputs
13181318
assert len(protocol_choices) > 0
@@ -1338,8 +1338,8 @@ def test_comprehensive_connection_type_coverage(self, realistic_model) -> None:
13381338
("RC Receiver", "FC Connection", "Type", "I2C1", False), # May not have protocols (not common for RC)
13391339
("Telemetry", "FC Connection", "Type", "None", True), # Should have protocols
13401340
("Telemetry", "FC Connection", "Type", "SERIAL1", True), # Should have protocols
1341-
("ESC", "FC Connection", "Type", "None", True), # Should have protocols
1342-
("ESC", "FC Connection", "Type", "CAN1", True), # Should have protocols
1341+
("ESC", "FC->ESC Connection", "Type", "None", True), # Should have protocols
1342+
("ESC", "FC->ESC Connection", "Type", "CAN1", True), # Should have protocols
13431343
("GNSS Receiver", "FC Connection", "Type", "None", True), # Should have protocols
13441344
("GNSS Receiver", "FC Connection", "Type", "SERIAL3", True), # Should have protocols
13451345
("Battery Monitor", "FC Connection", "Type", "None", True), # Should have protocols
@@ -1348,7 +1348,10 @@ def test_comprehensive_connection_type_coverage(self, realistic_model) -> None:
13481348

13491349
for component, section, field, value, should_have_protocols in test_cases:
13501350
model._update_possible_choices_for_path((component, section, field), value)
1351-
protocol_path = (component, "FC Connection", "Protocol")
1351+
if component == "ESC":
1352+
protocol_path = (component, "FC->ESC Connection", "Protocol")
1353+
else:
1354+
protocol_path = (component, "FC Connection", "Protocol")
13521355
protocol_choices = model._possible_choices.get(protocol_path, ())
13531356

13541357
if should_have_protocols:

tests/test_data_model_vehicle_components_validation_bdd.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ def test_user_sees_validation_errors_for_invalid_combobox_selections(self, valid
133133
invalid_entries = {
134134
("Battery", "Specifications", "Chemistry"): "UnknownChemistry", # Chemistry has combobox choices
135135
("RC Receiver", "FC Connection", "Protocol"): "InvalidProtocol", # RC Protocol has choices
136-
("ESC", "FC Connection", "Protocol"): "NonExistentProtocol", # ESC Protocol has choices
136+
("ESC", "FC->ESC Connection", "Protocol"): "NonExistentProtocol", # ESC Protocol has choices
137137
}
138138

139139
# Act: Validate all data
@@ -161,7 +161,7 @@ def test_user_sees_validation_errors_for_duplicate_fc_connections(self, validati
161161
# Arrange: Create entries with duplicate FC connections that are NOT allowed
162162
duplicate_entries = {
163163
("GNSS Receiver", "FC Connection", "Type"): "SERIAL2",
164-
("ESC", "FC Connection", "Type"): "SERIAL2", # Not allowed duplicate
164+
("ESC", "FC->ESC Connection", "Type"): "SERIAL2", # Not allowed duplicate
165165
("RC Receiver", "FC Connection", "Type"): "SERIAL3",
166166
(
167167
"Battery Monitor",
@@ -358,7 +358,7 @@ def test_validation_performance_with_large_dataset(self, validation_model) -> No
358358
large_entries[("Battery", "Specifications", "Chemistry")] = "InvalidChem" # Invalid combobox
359359
large_entries[("Battery", "Specifications", "Volt per cell max")] = "5.0" # Invalid battery voltage for Lipo
360360
large_entries[("RC Receiver", "FC Connection", "Type")] = "SERIAL1"
361-
large_entries[("ESC", "FC Connection", "Type")] = "SERIAL1" # Not allowed duplicate
361+
large_entries[("ESC", "FC->ESC Connection", "Type")] = "SERIAL1" # Not allowed duplicate
362362

363363
# Act: Validate all data
364364
is_valid, errors = validation_model.validate_all_data(large_entries)

tests/unit_data_model_vehicle_components_import.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -365,17 +365,17 @@ def test_set_battery_type_handles_type_error(self, realistic_model) -> None:
365365
realistic_model._set_battery_type_from_fc_parameters(fc_parameters)
366366
# pylint: enable=duplicate-code
367367

368-
def test_set_battery_type_handles_list_type_values(self, realistic_model) -> None:
368+
def test_set_battery_type_handles_tuple_type_values(self, realistic_model) -> None:
369369
"""
370-
Internal battery type setter handles list-type configuration values.
370+
Internal battery type setter handles tuple-type configuration values.
371371
372-
GIVEN: Battery configuration with list values for type and protocol
372+
GIVEN: Battery configuration with tuple values for type and protocol
373373
WHEN: Setting battery type from parameters
374-
THEN: First element of each list should be used
374+
THEN: First element of each tuple should be used
375375
"""
376376
with patch(
377377
"ardupilot_methodic_configurator.data_model_vehicle_components_import.BATT_MONITOR_CONNECTION",
378-
{"4": {"type": ["Analog", "Digital"], "protocol": ["Voltage", "Current"]}},
378+
{"4": {"type": ("Analog", "Digital"), "protocol": ("Voltage", "Current")}},
379379
):
380380
fc_parameters = {"BATT_MONITOR": 4}
381381
realistic_model._set_battery_type_from_fc_parameters(fc_parameters)

tests/unit_data_model_vehicle_components_validation.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,8 @@ def test_update_possible_choices_for_esc_can(self, realistic_model) -> None:
100100
model = realistic_model
101101
model.init_possible_choices({"MOT_PWM_TYPE": {"values": {"0": "Normal", "6": "DShot600"}}})
102102

103-
model._update_possible_choices_for_path(("ESC", "FC Connection", "Type"), "CAN1")
104-
protocol_choices = model._possible_choices.get(("ESC", "FC Connection", "Protocol"), ())
103+
model._update_possible_choices_for_path(("ESC", "FC->ESC Connection", "Type"), "CAN1")
104+
protocol_choices = model._possible_choices.get(("ESC", "FC->ESC Connection", "Protocol"), ())
105105

106106
assert protocol_choices == ("DroneCAN",)
107107

@@ -110,8 +110,8 @@ def test_update_possible_choices_for_esc_pwm(self, realistic_model) -> None:
110110
model = realistic_model
111111
model.init_possible_choices({"MOT_PWM_TYPE": {"values": {"0": "Normal", "6": "DShot600"}}})
112112

113-
model._update_possible_choices_for_path(("ESC", "FC Connection", "Type"), "Main Out")
114-
protocol_choices = model._possible_choices.get(("ESC", "FC Connection", "Protocol"), ())
113+
model._update_possible_choices_for_path(("ESC", "FC->ESC Connection", "Type"), "Main Out")
114+
protocol_choices = model._possible_choices.get(("ESC", "FC->ESC Connection", "Protocol"), ())
115115

116116
assert len(protocol_choices) > 0
117117
# pylint: enable=duplicate-code
@@ -244,7 +244,7 @@ def test_correct_display_values_preserves_key_values(self, validation_model) ->
244244
initial_data = {
245245
"Components": {
246246
"RC Receiver": {"FC Connection": {"Type": "SERIAL2"}},
247-
"ESC": {"FC Connection": {"Type": "CAN1"}},
247+
"ESC": {"FC->ESC Connection": {"Type": "CAN1"}},
248248
},
249249
"Format version": 1,
250250
}
@@ -258,7 +258,7 @@ def test_correct_display_values_preserves_key_values(self, validation_model) ->
258258

259259
# Assert
260260
assert model.get_component_value(("RC Receiver", "FC Connection", "Type")) == "SERIAL2"
261-
assert model.get_component_value(("ESC", "FC Connection", "Type")) == "CAN1"
261+
assert model.get_component_value(("ESC", "FC->ESC Connection", "Type")) == "CAN1"
262262

263263
def test_correct_display_values_handles_nested_data(self, validation_model) -> None:
264264
"""Test that correct_display_values_in_loaded_data() handles nested data structures."""

0 commit comments

Comments
 (0)