Skip to content

Commit b8eaf39

Browse files
committed
test(generated files): Add tests for generated files
1 parent 71c62b8 commit b8eaf39

4 files changed

Lines changed: 235 additions & 0 deletions

tests/gettext_capture_helper.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/usr/bin/env python3
2+
3+
"""
4+
Shared utilities for capturing gettext invocations in generated modules.
5+
6+
This file is part of ArduPilot Methodic Configurator. https://github.com/ArduPilot/MethodicConfigurator
7+
8+
SPDX-FileCopyrightText: 2024-2025 Amilcar do Carmo Lucas <amilcar.lucas@iav.de>
9+
10+
SPDX-License-Identifier: GPL-3.0-or-later
11+
"""
12+
13+
from collections.abc import Callable
14+
from types import ModuleType
15+
16+
import pytest
17+
18+
19+
def capture_gettext_calls(
20+
monkeypatch: pytest.MonkeyPatch,
21+
module: ModuleType,
22+
target: Callable[[], None],
23+
) -> list[str]:
24+
"""Patch module._ to record every string that flows through gettext."""
25+
captured_values: list[str] = []
26+
27+
def fake_gettext(value: str) -> str:
28+
captured_values.append(value)
29+
return value
30+
31+
monkeypatch.setattr(module, "_", fake_gettext)
32+
target()
33+
return captured_values
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#!/usr/bin/env python3
2+
3+
"""
4+
Behavior-driven datatype tests for configuration_steps_strings module.
5+
6+
This file is part of ArduPilot Methodic Configurator. https://github.com/ArduPilot/MethodicConfigurator
7+
8+
SPDX-FileCopyrightText: 2025 Amilcar do Carmo Lucas <amilcar.lucas@iav.de>
9+
10+
SPDX-License-Identifier: GPL-3.0-or-later
11+
"""
12+
13+
from gettext_capture_helper import capture_gettext_calls
14+
15+
from ardupilot_methodic_configurator import configuration_steps_strings as config_strings
16+
17+
18+
class TestConfigurationStepsStringsModule:
19+
"""BDD tests for string collection helpers."""
20+
21+
def test_configuration_steps_strings_invokes_gettext_with_text(self, monkeypatch) -> None:
22+
"""
23+
configuration_steps_strings forwards collected strings to gettext.
24+
25+
GIVEN: configuration_steps_strings aggregates literal strings from JSON resources
26+
WHEN: The gettext capture helper intercepts inputs
27+
THEN: Every captured value is a non-empty string and the function returns None
28+
"""
29+
captured_values = capture_gettext_calls(
30+
monkeypatch,
31+
config_strings,
32+
config_strings.configuration_steps_strings,
33+
)
34+
assert captured_values
35+
assert all(isinstance(value, str) and value for value in captured_values)
36+
37+
def test_configuration_steps_descriptions_invokes_gettext_with_text(self, monkeypatch) -> None:
38+
"""
39+
configuration_steps_descriptions forwards schema strings to gettext.
40+
41+
GIVEN: configuration_steps_descriptions enumerates strings from the schema file
42+
WHEN: The shared capture helper records gettext inputs
43+
THEN: Every value reaching gettext is a non-empty string and the function returns None
44+
"""
45+
captured_values = capture_gettext_calls(
46+
monkeypatch,
47+
config_strings,
48+
config_strings.configuration_steps_descriptions,
49+
)
50+
assert captured_values
51+
assert all(isinstance(value, str) and value for value in captured_values)
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#!/usr/bin/env python3
2+
3+
"""
4+
Behavior-driven tests that validate the structure of the data_model_fc_ids module.
5+
6+
This file is part of ArduPilot Methodic Configurator. https://github.com/ArduPilot/MethodicConfigurator
7+
8+
SPDX-FileCopyrightText: 2025 Amilcar do Carmo Lucas <amilcar.lucas@iav.de>
9+
10+
SPDX-License-Identifier: GPL-3.0-or-later
11+
"""
12+
13+
from ardupilot_methodic_configurator import data_model_fc_ids as fc_ids
14+
15+
16+
class TestFlightControllerIdsDataIntegrity:
17+
"""BDD-style tests ensuring the generated FC ID data keeps expected types."""
18+
19+
def test_vid_vendor_dict_ensures_int_keys_and_string_lists(self) -> None:
20+
"""
21+
VID vendor mapping uses integers and string lists.
22+
23+
GIVEN: The VID to vendor mapping contains multiple USB vendors
24+
WHEN: The mapping is inspected for datatype consistency
25+
THEN: Every key is an integer and every value is a non-empty list of strings
26+
"""
27+
for vid, vendors in fc_ids.VID_VENDOR_DICT.items():
28+
assert isinstance(vid, int)
29+
assert isinstance(vendors, list)
30+
assert vendors, "Vendor list must not be empty"
31+
assert all(isinstance(name, str) and name for name in vendors)
32+
33+
def test_vid_pid_product_dict_uses_tuple_keys_and_string_lists(self) -> None:
34+
"""
35+
VID/PID mapping stores tuple keys and string lists.
36+
37+
GIVEN: The VID/PID to product mapping represents USB products
38+
WHEN: The mapping is validated
39+
THEN: Keys are (int, int) tuples and values are non-empty string lists
40+
"""
41+
for key, products in fc_ids.VID_PID_PRODUCT_DICT.items():
42+
assert isinstance(key, tuple)
43+
assert len(key) == 2
44+
assert all(isinstance(part, int) for part in key)
45+
assert isinstance(products, list)
46+
assert products, "Product list must not be empty"
47+
assert all(isinstance(product, str) and product for product in products)
48+
49+
def test_apj_board_dicts_share_identical_keys_and_string_values(self) -> None:
50+
"""
51+
APJ board dictionaries expose matching key sets.
52+
53+
GIVEN: The APJ board dictionaries describe names, vendors, and MCU series
54+
WHEN: The dictionaries are compared
55+
THEN: They expose the same key set and each entry lists non-empty strings
56+
"""
57+
name_keys = set(fc_ids.APJ_BOARD_ID_NAME_DICT)
58+
vendor_keys = set(fc_ids.APJ_BOARD_ID_VENDOR_DICT)
59+
mcu_keys = set(fc_ids.APJ_BOARD_ID_MCU_SERIES_DICT)
60+
61+
assert name_keys == vendor_keys == mcu_keys
62+
63+
for board_id in name_keys:
64+
assert isinstance(board_id, int)
65+
names = fc_ids.APJ_BOARD_ID_NAME_DICT[board_id]
66+
vendors = fc_ids.APJ_BOARD_ID_VENDOR_DICT[board_id]
67+
mcu_series = fc_ids.APJ_BOARD_ID_MCU_SERIES_DICT[board_id]
68+
69+
assert isinstance(names, list)
70+
assert names
71+
assert isinstance(vendors, list)
72+
assert vendors
73+
assert isinstance(mcu_series, list)
74+
assert mcu_series
75+
assert all(isinstance(name, str) and name for name in names)
76+
assert all(isinstance(vendor, str) and vendor for vendor in vendors)
77+
assert all(isinstance(series, str) and series for series in mcu_series)
78+
79+
def test_mcu_series_mapping_references_known_board_ids(self) -> None:
80+
"""
81+
MCU series entries only reference known board IDs.
82+
83+
GIVEN: The MCU series to board ID mapping cross-references board metadata
84+
WHEN: The mapping is validated
85+
THEN: Every series is a string and every referenced ID exists in the board dictionaries
86+
"""
87+
known_board_ids = set(fc_ids.APJ_BOARD_ID_NAME_DICT)
88+
referenced_board_ids: set[int] = set()
89+
90+
for series, board_ids in fc_ids.MCU_SERIES_APJ_BOARD_ID_DICT.items():
91+
assert isinstance(series, str)
92+
assert series
93+
assert isinstance(board_ids, list)
94+
assert board_ids
95+
assert all(isinstance(board_id, int) and board_id in known_board_ids for board_id in board_ids)
96+
referenced_board_ids.update(board_ids)
97+
98+
assert referenced_board_ids.issuperset(known_board_ids)
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#!/usr/bin/env python3
2+
3+
"""
4+
Behavior-driven datatype tests for vehicle_components translation helpers.
5+
6+
This file is part of ArduPilot Methodic Configurator. https://github.com/ArduPilot/MethodicConfigurator
7+
8+
SPDX-FileCopyrightText: 2025 Amilcar do Carmo Lucas <amilcar.lucas@iav.de>
9+
10+
SPDX-License-Identifier: GPL-3.0-or-later
11+
"""
12+
13+
from gettext_capture_helper import capture_gettext_calls
14+
15+
from ardupilot_methodic_configurator import vehicle_components
16+
17+
18+
class TestVehicleComponentsTranslationHelpers:
19+
"""BDD coverage for vehicle component translation helpers."""
20+
21+
def test_translatable_strings_forward_literals_to_gettext(self, monkeypatch) -> None:
22+
"""
23+
translatable_strings forwards every literal to gettext.
24+
25+
GIVEN: translatable_strings simply enumerates literal strings
26+
WHEN: The shared gettext capture helper records inputs
27+
THEN: The recorder captures non-empty strings exclusively
28+
"""
29+
captured_values = capture_gettext_calls(
30+
monkeypatch,
31+
vehicle_components,
32+
vehicle_components.translatable_strings,
33+
)
34+
35+
assert captured_values
36+
assert all(isinstance(value, str) and value for value in captured_values)
37+
38+
def test_translatable_descriptions_forward_literals_to_gettext(self, monkeypatch) -> None:
39+
"""
40+
translatable_descriptions forwards schema literals to gettext.
41+
42+
GIVEN: translatable_descriptions iterates strings from the schema definition
43+
WHEN: The helper intercepts gettext invocations
44+
THEN: The recorder receives only non-empty strings
45+
"""
46+
captured_values = capture_gettext_calls(
47+
monkeypatch,
48+
vehicle_components,
49+
vehicle_components.translatable_descriptions,
50+
)
51+
52+
assert captured_values
53+
assert all(isinstance(value, str) and value for value in captured_values)

0 commit comments

Comments
 (0)