Skip to main content

tdd

Test-driven development for firmware logic using PlatformIO's native env. TRIGGER when adding or changing code under lib/sampler/, lib/packetizer/, lib/ringbuf/, lib/config/, or any pure-logic C++ in this repo. DO NOT trigger for docs, platformio.ini, scripts, or hardware-only modules (lib/imu/, lib/net/, lib/uploader/) where behavior can't be exercised without a board.

Informations de source

Dépôt
weaties/imu4helmlog
Dernière activité de la source
14 avril 2026 à 21:55
Langue détectée de SKILL.md
anglais
Étoiles
0
Forks
0

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
tdd
description
Test-driven development for firmware logic using PlatformIO's native env. TRIGGER when adding or changing code under lib/sampler/, lib/packetizer/, lib/ringbuf/, lib/config/, or any pure-logic C++ in this repo. DO NOT trigger for docs, platformio.ini, scripts, or hardware-only modules (lib/imu/, lib/net/, lib/uploader/) where behavior can't be exercised without a board.
# TDD — host-side firmware loop Embedded TDD only works if you can run the code on the host. This project is structured so that every non-hardware module builds and tests under `pio test -e native` on the Mac in under a second. Use that ruthlessly. ## The cycle ### 1. Red — failing host test Add a test file under `test/test_native/test_<module>/test_<module>.cpp`. PlatformIO + Unity discovers one `void setup()` / `void loop()` per group. ```cpp #include <unity.h> #include "packetizer/Packetizer.h" void test_batch_respects_size_cap(void) { Packetizer p(/*cap=*/10); for (int i = 0; i < 15; i++) p.add(sample_at(i)); TEST_ASSERT_EQUAL(10, p.size()); TEST_ASSERT_EQUAL(5, p.dropped()); } void setup() { UNITY_BEGIN(); RUN_TEST(test_batch_respects_size_cap); UNITY_END(); } void loop() {} ``` Run it and confirm it **fails for the reason you expect**, not a link error: ```bash pio test -e native -f test_packetizer ``` ### 2. Green — minimum implementation Write the least code that makes it pass. No speculative generality. Sampler rate logic doesn't need a state machine if an `if` works. ```bash pio test -e native -f test_packetizer ``` ### 3. Refactor — run the whole host suite ```bash pio test -e native ``` All host tests must be green. If a refactor touches the interface between a pure-logic module and a hardware module, also verify the device build still links: ```bash pio run -e esp32c3 ``` ### 4. Format ```bash clang-format -i $(git ls-files 'src/*.cpp' 'src/*.h' 'lib/**/*.cpp' 'lib/**/*.h' 'test/**/*.cpp' 'test/**/*.h') ``` ### 5. Commit Test and implementation in the same commit. Conventional commit format, include issue number if applicable: `feat(packetizer): cap batch size (#12)`. ## What belongs in host tests - **Packetizer** — JSON shape, `seq` monotonicity, mount_quat application, batch boundaries, gzip framing, pre_sntp handling - **Sampler** — rate limiting, backpressure when ringbuf is full, clock skew detection, dropped-sample accounting - **Ringbuf** — wrap behavior, oldest-drop-on-overflow, segment recovery after simulated crash, size accounting - **Config** — NVS round-trip (use a fake NVS), schema version migration, default values - **Anything with math** — quaternion multiplication, frame transforms, heave integration — write a test with known-answer inputs ## What does NOT belong in host tests - `lib/imu/` device impl — needs `Wire` and `sh2`, use `ImuFake` in host tests - `lib/net/` — uses `WiFi.h`, mock at the interface boundary - `lib/uploader/` — uses `HTTPClient`, inject a fake HTTP sink - `main.cpp` — no logic lives there by convention; nothing to test If you catch yourself writing `#ifdef ARDUINO` inside a module that's supposed to be pure logic, stop — the hardware dependency needs to move behind an interface. ## Fake injection pattern ```cpp // lib/imu/Imu.h class Imu { public: virtual ~Imu() = default; virtual bool begin() = 0; virtual bool read(Sample& out) = 0; }; // lib/imu/ImuFake.h — host-only class ImuFake : public Imu { public: std::vector<Sample> canned; size_t idx = 0; bool begin() override { return true; } bool read(Sample& out) override { if (idx >= canned.size()) return false; out = canned[idx++]; return true; } }; ``` Sampler takes `Imu&`, not `Imu*` or a concrete type. Tests pass `ImuFake`. `main.cpp` passes the real one. ## Known gotchas - **Unity's `TEST_ASSERT_EQUAL_FLOAT` uses a fixed epsilon** — for quaternion math, use `TEST_ASSERT_FLOAT_WITHIN(1e-6f, expected, actual)` - **`pio test -e native` rebuilds slowly on cold cache** — first run takes ~15s, subsequent runs are sub-second. Don't conflate the two - **Arduino types leak in** — if a host test fails to compile because of `String` or `HardwareSerial`, the module under test has a hidden Arduino dependency. Move it behind an interface
Voir sur GitHub