diff --git a/tests/runner/mpremote_bridge.py b/tests/runner/mpremote_bridge.py index 11bba3b9..58465195 100644 --- a/tests/runner/mpremote_bridge.py +++ b/tests/runner/mpremote_bridge.py @@ -49,9 +49,11 @@ def _run(self, code, mount_dir=None): result = subprocess.run(cmd, capture_output=True, text=True, timeout=30, check=False) if result.returncode != 0: - raise RuntimeError( - f"mpremote failed: {result.stderr.strip()}" - ) + stderr = result.stderr.strip() + stdout = result.stdout.strip() + parts = [p for p in (stderr, stdout) if p] + detail = "\n".join(parts) or "(no output)" + raise RuntimeError(f"mpremote failed: {detail}") # mpremote mount adds "Local directory ... is mounted at /remote" # to stdout; filter it out and keep only the script output lines = [ @@ -142,20 +144,33 @@ def run_script( last_line = output.strip().rsplit("\n", 1)[-1] return json.loads(last_line) - def run_raw_script(self, script): + def run_raw_script(self, script, mount_dir=None): """Run a raw MicroPython script on the board without driver context. The script must set a ``result`` variable. Returns the JSON-decoded value of ``result``. + + Args: + mount_dir: optional local directory to mount on the board. """ code = ( f"import json\n" f"{script}\n" f"print(json.dumps(result))" ) - output = self._run(code) - last_line = output.strip().rsplit("\n", 1)[-1] - return json.loads(last_line) + output = self._run(code, mount_dir=mount_dir) + lines = output.strip().splitlines() + # Print non-JSON lines (diagnostic output from the script) + for line in lines[:-1]: + print(line) + last_line = lines[-1] if lines else "" + try: + return json.loads(last_line) + except json.JSONDecodeError: + full = "\n".join(lines) + raise RuntimeError( + f"Script did not produce valid JSON result.\nFull output:\n{full}" + ) def scan_bus(self, i2c_config): """Scan I2C bus and return list of addresses.""" diff --git a/tests/scenarios/board_temperature_comparison.yaml b/tests/scenarios/board_temperature_comparison.yaml new file mode 100644 index 00000000..11a1b654 --- /dev/null +++ b/tests/scenarios/board_temperature_comparison.yaml @@ -0,0 +1,107 @@ +type: board +name: "Temperature comparison (all sensors)" + +i2c: + id: 1 + +# List of drivers needed — triggers mounting lib/ via mpremote +drivers: + - hts221 + - wsen-hids + - wsen-pads + - lis2mdl + +tests: + - name: "Read all temperature sensors" + action: hardware_script + script: | + import sys + sys.path.insert(0, '/remote/hts221') + sys.path.insert(0, '/remote/wsen-hids') + sys.path.insert(0, '/remote/wsen-pads') + sys.path.insert(0, '/remote/lis2mdl') + + from machine import I2C + from time import sleep_ms + + i2c = I2C(1) + + temps = {} + + # HTS221 + from hts221.device import HTS221 + hts = HTS221(i2c) + hts.poweroff() + sleep_ms(20) + hts.poweron() + sleep_ms(50) + temps['HTS221'] = hts.temperature() + + # WSEN-HIDS + from wsen_hids.device import WSEN_HIDS + hids = WSEN_HIDS(i2c) + temps['WSEN-HIDS'] = hids.temperature() + + # WSEN-PADS + from wsen_pads.device import WSEN_PADS + pads = WSEN_PADS(i2c) + temps['WSEN-PADS'] = pads.temperature() + + # LIS2MDL (auxiliary, offset not guaranteed by datasheet) + from lis2mdl.device import LIS2MDL + mag = LIS2MDL(i2c) + temps['LIS2MDL'] = mag.read_temperature_c() + + # Print comparison table + print('--- Temperature Comparison ---') + for name, t in temps.items(): + pad = ' ' * (12 - len(name)) + print(' ' + name + pad + ': ' + str(round(t, 2)) + ' C') + + # Check thermometers in plausible range (HTS221, WSEN-HIDS, WSEN-PADS) + thermometers = [temps['HTS221'], temps['WSEN-HIDS'], temps['WSEN-PADS']] + all_ok = all(5.0 <= t <= 50.0 for t in thermometers) + + # Check spread between thermometers + spread = max(thermometers) - min(thermometers) + print(' Spread: ' + str(round(spread, 2)) + ' C') + + result = all_ok and spread < 8.0 + expect_true: true + mode: [hardware] + + - name: "Temperature spread with barometer" + action: hardware_script + script: | + import sys + sys.path.insert(0, '/remote/hts221') + sys.path.insert(0, '/remote/wsen-pads') + + from machine import I2C + from time import sleep_ms + + i2c = I2C(1) + + from hts221.device import HTS221 + hts = HTS221(i2c) + hts.poweroff() + sleep_ms(20) + hts.poweron() + sleep_ms(50) + t_hts = hts.temperature() + + from wsen_pads.device import WSEN_PADS + pads = WSEN_PADS(i2c) + t_pads = pads.temperature() + + spread = abs(t_hts - t_pads) + print(' HTS221: ' + str(round(t_hts, 2)) + ' C | WSEN-PADS: ' + str(round(t_pads, 2)) + ' C | Spread: ' + str(round(spread, 2)) + ' C') + result = spread < 5.0 + expect_true: true + mode: [hardware] + + - name: "Temperature values feel correct" + action: manual + prompt: "Les températures lues sont-elles cohérentes entre elles et avec l'ambiance ?" + expect_true: true + mode: [hardware] diff --git a/tests/test_scenarios.py b/tests/test_scenarios.py index d17fccd1..16e2aa6d 100644 --- a/tests/test_scenarios.py +++ b/tests/test_scenarios.py @@ -172,7 +172,12 @@ def test_scenario(scenario, test, mode, port): else: print(f" [INTERACTIVE] {pre_prompt}") if is_board: - result = bridge.run_raw_script(test["script"]) + mount_dir = None + if scenario.get("drivers"): + mount_dir = Path(__file__).parent.parent / "lib" + result = bridge.run_raw_script( + test["script"], mount_dir=mount_dir, + ) else: result = bridge.run_script( scenario["driver"],