diff --git a/tests/runner/mpremote_bridge.py b/tests/runner/mpremote_bridge.py index 705f19b1..b50ee5b6 100644 --- a/tests/runner/mpremote_bridge.py +++ b/tests/runner/mpremote_bridge.py @@ -67,12 +67,15 @@ def _driver_dir(self, driver_name): def call_method( self, driver_name, driver_class, i2c_config, method, args=None, i2c_address=None, module_name=None, + hardware_init=None, ): """Call a method on a driver instance and return the result.""" mod = module_name or driver_name args_str = ", ".join(repr(a) for a in (args or [])) i2c_init = _i2c_init_code(i2c_config) - if i2c_address is not None: + if hardware_init is not None: + dev_init = hardware_init + "\n" + elif i2c_address is not None: dev_init = f"dev = {driver_class}(i2c, address={i2c_address!r})\n" else: dev_init = f"dev = {driver_class}(i2c)\n" diff --git a/tests/scenarios/apds9960.yaml b/tests/scenarios/apds9960.yaml new file mode 100644 index 00000000..82987d3b --- /dev/null +++ b/tests/scenarios/apds9960.yaml @@ -0,0 +1,105 @@ +driver: apds9960 +driver_class: uAPDS9960 +i2c_address: 0x39 + +# I2C config for hardware tests (STeaMi board - STM32WB55) +i2c: + id: 1 + +# Custom hardware init (enable light and proximity sensors before reading) +hardware_init: | + from time import sleep + dev = uAPDS9960(i2c) + dev.enableLightSensor(False) + dev.enableProximitySensor(False) + sleep(0.3) + +# Register values for mock tests +mock_registers: + # ID register (0x92): expected 0xAB + 0x92: 0xAB + # ENABLE (0x80): power off at start + 0x80: 0x00 + # CONTROL (0x8F): used by read-modify-write in init + 0x8F: 0x00 + # CONFIG2 (0x90): default + 0x90: 0x01 + # CONFIG3 (0x9F): default + 0x9F: 0x00 + # GCONF2 (0xA3): used by gesture config + 0xA3: 0x00 + # GCONF4 (0xAB): used by gesture config + 0xAB: 0x00 + # STATUS (0x93): AVALID + PVALID + 0x93: 0x03 + # Ambient light: clear channel = 256 (0x0100) + 0x94: 0x00 # CDATAL + 0x95: 0x01 # CDATAH + # Red = 128 + 0x96: 0x80 # RDATAL + 0x97: 0x00 # RDATAH + # Green = 64 + 0x98: 0x40 # GDATAL + 0x99: 0x00 # GDATAH + # Blue = 32 + 0x9A: 0x20 # BDATAL + 0x9B: 0x00 # BDATAH + # Proximity = 80 + 0x9C: 0x50 + +tests: + - name: "Verify device ID register (mock)" + action: call + method: _read_byte_data + args: [0x92] + expect: 0xAB + mode: [mock] + + - name: "Verify device ID register (hardware)" + action: read_register + register: 0x92 + expect: 0xAB + mode: [hardware] + + - name: "Read ambient light returns expected value" + action: call + method: readAmbientLight + expect: 256 + mode: [mock] + + - name: "Read proximity returns expected value" + action: call + method: readProximity + expect: 80 + mode: [mock] + + - name: "Read red light returns expected value" + action: call + method: readRedLight + expect: 128 + mode: [mock] + + - name: "Ambient light in plausible range" + action: call + method: readAmbientLight + expect_range: [1, 65535] + mode: [hardware] + + - name: "Proximity in plausible range" + action: call + method: readProximity + expect_range: [0, 255] + mode: [hardware] + + - name: "Light and proximity values feel correct" + action: manual + display: + - method: readAmbientLight + label: "Ambient light" + unit: "" + - method: readProximity + label: "Proximity" + unit: "" + prompt: "Les valeurs de lumière ambiante et de proximité sont-elles cohérentes ?" + expect_true: true + mode: [hardware] diff --git a/tests/test_scenarios.py b/tests/test_scenarios.py index 3906501c..6a5a38ce 100644 --- a/tests/test_scenarios.py +++ b/tests/test_scenarios.py @@ -6,6 +6,7 @@ import pytest from tests.fake_machine.i2c import FakeI2C +from tests.fake_machine.pin import FakePin from tests.runner.executor import ( check_result, cleanup_driver, @@ -59,8 +60,13 @@ def make_mock_instance(scenario): fake_i2c = FakeI2C(registers=registers, address=address) driver_module, _ = load_driver_mock(driver_name, fake_i2c, module_name=module_name) + # Build extra constructor kwargs from mock_pins + extra_kwargs = {} + for pin_name, pin_id in scenario.get("mock_pins", {}).items(): + extra_kwargs[pin_name] = FakePin(pin_id) + cls = getattr(driver_module, driver_class) - instance = cls(fake_i2c, address=address) + instance = cls(fake_i2c, address=address, **extra_kwargs) return instance, driver_name @@ -92,6 +98,7 @@ def test_scenario(scenario, test, mode, port): display["method"], display.get("args"), module_name=scenario.get("module_name"), + hardware_init=scenario.get("hardware_init"), ) label = display.get("label", display["method"]) unit = display.get("unit", "") @@ -110,6 +117,7 @@ def test_scenario(scenario, test, mode, port): test["method"], test.get("args"), module_name=scenario.get("module_name"), + hardware_init=scenario.get("hardware_init"), ) elif action == "read_register": result = bridge.read_register(