diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1c14a1e3..616a5d64 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,7 +40,7 @@ jobs: - uses: ./.github/actions/setup - name: Run fast tests itself with pytest run: | - pipenv run pytest -m 'not skip_ci and not slow' test + pipenv run pytest -m 'not skip_ci and not slow and not one_anki_car_needed' test pytest-testing-slow: name: Run slow tests with pytest diff --git a/pytest.ini b/pytest.ini index a69a3831..422de75f 100644 --- a/pytest.ini +++ b/pytest.ini @@ -7,6 +7,6 @@ markers = anki_cars_driving: marks tests that require Anki cars placed on a race track anki_car_placed_on_charger: marks tests that require one Anki car placed on the charging station anki_car_removed_from_charger: marks tests that require one Anki car placed NOT on the charging station - skip_ci: marks tests that require something that isn't accessible in the CI like physical cars + skip_ci: marks tests that require something that is not accessible in the CI like physical cars pythonpath = src python_files = *Test.py diff --git a/src/DataModel/Vehicle.py b/src/DataModel/Vehicle.py index fd46d011..7dcad7ea 100644 --- a/src/DataModel/Vehicle.py +++ b/src/DataModel/Vehicle.py @@ -22,7 +22,10 @@ class Vehicle: - def __init__(self, vehicle_id: str, location_service: LocationService, disable_item_removal: bool = False) -> None: + def __init__(self, vehicle_id: str, + location_service: LocationService, + disable_item_removal: bool = False) -> None: + self.vehicle_id: str = vehicle_id self.player: str | None = None self.game_start: datetime | None = None diff --git a/src/EnvironmentManagement/EnvironmentManager.py b/src/EnvironmentManagement/EnvironmentManager.py index e34b2240..456eae5d 100644 --- a/src/EnvironmentManagement/EnvironmentManager.py +++ b/src/EnvironmentManagement/EnvironmentManager.py @@ -47,7 +47,8 @@ class RemovalReason(Enum): class EnvironmentManager: - def __init__(self, fleet_ctrl: FleetController, + def __init__(self, + fleet_ctrl: FleetController, configuration_handler: ConfigurationHandler = ConfigurationHandler()): self._fleet_ctrl: FleetController = fleet_ctrl diff --git a/src/Items/ItemCollisionDetection.py b/src/Items/ItemCollisionDetection.py index 8f4a0b4d..98e40ea3 100644 --- a/src/Items/ItemCollisionDetection.py +++ b/src/Items/ItemCollisionDetection.py @@ -7,9 +7,13 @@ class ItemCollisionDetector: - def __init__(self): + def __init__(self, + configuration_handler: ConfigurationHandler = ConfigurationHandler()) -> None: + + self.config_handler: ConfigurationHandler = configuration_handler self._items: list[Item] = [] self._on_item_change: Callable[[list[Item]], None] | None = None + return def notify_new_vehicle_position(self, vehicle: Vehicle, vehicle_position: Position, vehicle_rotation: Angle): for item in self._items: @@ -23,7 +27,7 @@ def set_on_item_change_callback(self, callback: Callable[[list[Item]], None]): self._on_item_change = callback def add_item(self, item: Item): - config = ConfigurationHandler().get_configuration() + config = self.config_handler.get_configuration() max_item_length = config['item']['item_max_count'] - 1 if len(self._items) <= max_item_length: self._items.append(item) diff --git a/src/UserInterface/DriverUI.py b/src/UserInterface/DriverUI.py index c2073ca3..f25e732a 100644 --- a/src/UserInterface/DriverUI.py +++ b/src/UserInterface/DriverUI.py @@ -19,7 +19,7 @@ from DataModel.Vehicle import Vehicle from EnvironmentManagement.EnvironmentManager import EnvironmentManager from EnvironmentManagement.ConfigurationHandler import ConfigurationHandler -from VehicleMovementManagement import BehaviourController +from VehicleMovementManagement.BehaviourController import BehaviourController logger = logging.getLogger(__name__) diff --git a/test/UnitTest/DataModel/Vehicle_Test.py b/test/UnitTest/DataModel/Vehicle_Test.py index 7f2cbcfb..9ab8c59f 100644 --- a/test/UnitTest/DataModel/Vehicle_Test.py +++ b/test/UnitTest/DataModel/Vehicle_Test.py @@ -9,7 +9,6 @@ from DataModel.Vehicle import Vehicle from Items.Item import Item from LocationService.LocationService import LocationService -from VehicleManagement.VehicleController import VehicleController from VehicleManagement.FleetController import FleetController dummy_uuid = "FA:14:67:0F:39:FE" @@ -21,19 +20,20 @@ def init_vehicle(): return Vehicle('123', location_service_mock, disable_item_removal=True) -@pytest.mark.skip_ci -def test_get_location(): - vctrl = VehicleController() +@pytest.mark.one_anki_car_needed +@pytest.mark.asyncio +async def test_get_location(): + loc_Service = LocationService(None) fleet_ctrl = FleetController() - found_vehicles = fleet_ctrl.scan_for_anki_cars() - mut = Vehicle(found_vehicles[0], vctrl) + found_vehicles = await fleet_ctrl.scan_for_anki_cars() + mut = Vehicle(found_vehicles[0], loc_Service) - mut.speed_request = 80.0 + mut.request_speed_percent(80.0) sleep(5) - mut.speed_request = 0.0 + mut.request_speed_percent(0.0) assert mut diff --git a/test/UnitTest/EnvironmentManagement/EnvironmentManager_Test.py b/test/UnitTest/EnvironmentManagement/EnvironmentManager_Test.py index 0395d713..9e3ea968 100644 --- a/test/UnitTest/EnvironmentManagement/EnvironmentManager_Test.py +++ b/test/UnitTest/EnvironmentManagement/EnvironmentManager_Test.py @@ -25,8 +25,11 @@ def initialise_dependencies(): @pytest.fixture(scope="module") def get_mut_with_one_minute_playing_time(initialise_dependencies) -> EnvironmentManager: fleet_ctrl_mock, configuration_handler_mock = initialise_dependencies - configuration_handler_mock.get_configuration.return_value = \ - {"game_config": {"game_cfg_playing_time_limit_min": 1}} + configuration_handler_mock.get_configuration.return_value = { + "virtual_cars_pics": {"AB:CD:EF:12:34:56": "ABCDEF123456.svg", + "GH:IJ:KL:78:90:21": "GHIJKL789021.svg"}, + "driver": {"key1": "value1", "key2": "value2"}, + "game_config": {"game_cfg_playing_time_limit_min": 1}} mut: EnvironmentManager = EnvironmentManager(fleet_ctrl_mock, configuration_handler_mock) @@ -36,8 +39,12 @@ def get_mut_with_one_minute_playing_time(initialise_dependencies) -> Environment @pytest.fixture def get_mut_with_endless_playing_time(initialise_dependencies) -> EnvironmentManager: fleet_ctrl_mock, configuration_handler_mock = initialise_dependencies - configuration_handler_mock.get_configuration.return_value = \ - {"game_config": {"game_cfg_playing_time_limit_min": 0}} + + configuration_handler_mock.get_configuration.return_value = { + "virtual_cars_pics": {"AB:CD:EF:12:34:56": "ABCDEF123456.svg", + "GH:IJ:KL:78:90:21": "GHIJKL789021.svg"}, + "driver": {"key1": "value1", "key2": "value2"}, + "game_config": {"game_cfg_playing_time_limit_min": 0}} mut: EnvironmentManager = EnvironmentManager(fleet_ctrl_mock, configuration_handler_mock) @@ -73,15 +80,15 @@ def get_one_dummy_vehicle() -> Vehicle: @pytest.fixture def create_inputs_with_expected_false(request): input_values = request.instance.invalid_player_ids - testparameter: list[(str, bool)] = [(input_value, False) for input_value in input_values] + testparameter: list[tuple[str, bool]] = [(input_value, False) for input_value in input_values] return testparameter -def create_inputs(input_values: list[str] = None) -> list[(str, bool)]: +def create_inputs(input_values: list[str | int | float] | None = None) -> list[tuple[str | int | float, bool]]: if input_values is None: input_values = ["", " ", "@#$%^&*()", 2, 3.5] - testparameter: list[(str, bool)] = [(input_value, False) for input_value in input_values] + testparameter: list[tuple[str | int | float, bool]] = [(input_value, False) for input_value in input_values] return testparameter diff --git a/test/UnitTest/Items/ItemCollection_Test.py b/test/UnitTest/Items/ItemCollection_Test.py index a5d3d2ff..8797305c 100644 --- a/test/UnitTest/Items/ItemCollection_Test.py +++ b/test/UnitTest/Items/ItemCollection_Test.py @@ -1,23 +1,31 @@ -from unittest.mock import MagicMock +from unittest.mock import Mock from DataModel.Vehicle import Vehicle from Items.Item import Item from Items.ItemCollisionDetection import ItemCollisionDetector from LocationService.Trigo import Position, Angle +from EnvironmentManagement.ConfigurationHandler import ConfigurationHandler def test_item_collision_notification(): """ This tests that an item is only collected, when a location is reported that is in proximity """ - item = MagicMock(spec=Item) - item.get_position.return_value = Position(100, 100) + item_Mock = Mock(spec=Item) + configuration_handler_mock = Mock(spec=ConfigurationHandler) + configuration_handler_mock.get_configuration.return_value = { + "virtual_cars_pics": {"AB:CD:EF:12:34:56": "ABCDEF123456.svg", + "GH:IJ:KL:78:90:21": "GHIJKL789021.svg"}, + "driver": {"key1": "value1", "key2": "value2"}, + "game_config": {"game_cfg_playing_time_limit_min": 1}, + "item": {"item_max_count": 1}} + item_Mock.get_position.return_value = Position(100, 100) - item_collision_detector = ItemCollisionDetector() + item_collision_detector = ItemCollisionDetector(configuration_handler_mock) item_collision_detector._items.clear() - item_collision_detector._items.append(item) + item_collision_detector._items.append(item_Mock) - vehicle_mock = MagicMock(spec=Vehicle) + vehicle_mock = Mock(spec=Vehicle) item_collision_detector.notify_new_vehicle_position(vehicle_mock, Position(1000, 900), Angle(0)) vehicle_mock.notify_item_collected.assert_not_called() item_collision_detector.notify_new_vehicle_position(vehicle_mock, Position(1000, 30), Angle(0)) @@ -27,27 +35,35 @@ def test_item_collision_notification(): item_collision_detector.notify_new_vehicle_position(vehicle_mock, Position(95, 105), Angle(0)) vehicle_mock.notify_item_collected.assert_called() - vehicle_mock.notify_item_collected.assert_called_with(item) + vehicle_mock.notify_item_collected.assert_called_with(item_Mock) def test_callbacks_are_executed(): """ This tests that when an item gets added or removed the callback is executed """ - item = MagicMock(spec=Item) - item_changed_callback = MagicMock() - item_collision_detector = ItemCollisionDetector() - item_collision_detector.set_on_item_change_callback(item_changed_callback) + itemMock = Mock(spec=Item) + configuration_handler_mock = Mock(spec=ConfigurationHandler) + configuration_handler_mock.get_configuration.return_value = { + "virtual_cars_pics": {"AB:CD:EF:12:34:56": "ABCDEF123456.svg", + "GH:IJ:KL:78:90:21": "GHIJKL789021.svg"}, + "driver": {"key1": "value1", "key2": "value2"}, + "game_config": {"game_cfg_playing_time_limit_min": 1}, + "item": {"item_max_count": 1}} + item_changed_callback = Mock() - item_collision_detector.add_item(item) + mut = ItemCollisionDetector(configuration_handler_mock) + mut.set_on_item_change_callback(item_changed_callback) + + mut.add_item(itemMock) item_changed_callback.assert_called() item_changed_callback.reset_mock() - item_collision_detector.remove_item(item) + mut.remove_item(itemMock) item_changed_callback.assert_called() item_changed_callback.reset_mock() - item_collision_detector.clear_items() + mut.clear_items() item_changed_callback.assert_called() diff --git a/test/UnitTest/LocationService/FullTrack_Test.py b/test/UnitTest/LocationService/FullTrack_Test.py index b4f8e14c..ffd55fbd 100644 --- a/test/UnitTest/LocationService/FullTrack_Test.py +++ b/test/UnitTest/LocationService/FullTrack_Test.py @@ -5,7 +5,7 @@ @pytest.fixture -def standard_track() -> FullTrack: +def small_track() -> FullTrack: track: FullTrack = TrackBuilder() \ .append(TrackPieceType.STRAIGHT_WE) \ .append(TrackPieceType.CURVE_WS) \ @@ -52,14 +52,13 @@ def big_track() -> FullTrack: return track -def test_track_size_calculation(standard_track, big_track): +def test_track_size_calculation(small_track: FullTrack, big_track: FullTrack): track_square_size = 559 - small_track, big_track = standard_track, big_track size_small = small_track.get_used_space_as_dict() size_big = big_track.get_used_space_as_dict() - assert pytest.approx(track_square_size * 2) == size_small['used_space_vertically'] - assert pytest.approx(track_square_size * 3) == size_small['used_space_horizontally'] + assert pytest.approx(track_square_size * 3) == size_small['used_space_vertically'] + assert pytest.approx(track_square_size * 2) == size_small['used_space_horizontally'] - assert pytest.approx(track_square_size * 4) == size_big['used_space_vertically'] - assert pytest.approx(track_square_size * 7) == size_big['used_space_horizontally'] + assert pytest.approx(track_square_size * 7) == size_big['used_space_vertically'] + assert pytest.approx(track_square_size * 4) == size_big['used_space_horizontally'] diff --git a/test/UnitTest/UserInterface/DriverUI_Test.py b/test/UnitTest/UserInterface/DriverUI_Test.py index 3e2b4549..3df44c69 100644 --- a/test/UnitTest/UserInterface/DriverUI_Test.py +++ b/test/UnitTest/UserInterface/DriverUI_Test.py @@ -20,8 +20,11 @@ def initialise_dependencies(): Prepare a DriverUI, Environment Vehicle and Vehicle """ configuration_handler_mock = MagicMock(spec=ConfigurationHandler) - configuration_handler_mock.get_configuration.return_value = \ - {"game_config": {"game_cfg_playing_time_limit_min": 0}} + configuration_handler_mock.get_configuration.return_value = { + "virtual_cars_pics": {"AB:CD:EF:12:34:56": "ABCDEF123456.svg", + "GH:IJ:KL:78:90:21": "GHIJKL789021.svg"}, + "driver": {"key1": "value1", "key2": "value2"}, + "game_config": {"game_cfg_playing_time_limit_min": 0}} socket = AsyncServer(async_mode='asgi') fleet_ctrl = FleetController()