Testing Methodology
Relevant source files
The following files were used as context for generating this wiki page:
The OpenAwair project employs a structured testing strategy focused on validating the TypeScript host-side tooling and device abstractions. The methodology relies on a native Node.js testing framework to ensure the reliability of critical path operations such as Device Firmware Updates (DFU), MQTT communication, and RESTful API routing. This approach ensures that the host-side logic correctly models and interacts with the hardware components before full C/C++ implementation.
Sources: CLAUDE.md:41-48, README.md:14-16
Test Framework and Environment
The project utilizes the native Node.js node:test module combined with node:assert/strict for its test suite. Tests are written in TypeScript using ESM-style imports and are compiled to CommonJS before execution.
Execution Workflow
The testing lifecycle is managed through NPM scripts defined in the root package.json. The process involves three primary steps:
- Compilation: TypeScript files in the
host/directory are compiled usingtsc. - Output: Compiled JavaScript is placed in the
dist/directory. - Execution: The Node.js test runner executes the compiled files in
dist/test/.
The following table describes the scripts available for testing and quality assurance:
| Command | Action | Purpose |
|---|---|---|
npm run typecheck | tsc -p host/tsconfig.json --noEmit | Validates TypeScript types without generating files. |
npm run lint | tsc -p host/tsconfig.lint.json --noEmit | Performs strict linting for unused variables and parameters. |
npm run test | tsc ... && node --test dist/test/*.js | Compiles source and runs the full test suite. |
Sources: package.json:7-11, CLAUDE.md:27-33, host/tsconfig.lint.json:1-7
Unit Testing Modules
Networking and Communication
Tests for networking components ensure that telemetry data is correctly formatted for different protocols and that routing logic behaves as expected.
- MQTT Testing: Validates the
MqttPublisherandmqttDiscoverylogic. It ensures that telemetry payloads include required device identifiers and that Home Assistant discovery messages follow the expected topic structure. - REST Routing: Exercises the
RestRouterby registering mock endpoints and verifying that HTTP methods and paths resolve to the correct handlers or return 404 for missing resources.
Sources: host/test/mqtt.test.ts:1-24, host/test/mqttDiscovery.test.ts:1-32, host/test/restRouter.test.ts:1-28
Firmware and Bootloader Logic
Critical firmware-related processes, specifically DFU and data integrity, are heavily tested to prevent device bricking during updates.
- DFU Sessions: Tests the
DfuSessionclass by simulating chunked firmware transfers. The tests verify that the session correctly tracks received data, handles offsets, and performs a final CRC32 validation against the expected checksum. - Checksum Verification: A dedicated test for the
crc32utility ensures that the algorithm produces stable, known-good checksums for arbitrary data buffers.
Sources: host/test/dfu.test.ts:1-23, host/test/crc32.test.ts:1-12
Data Validation Flow
The following sequence diagram illustrates how a DFU session is validated during a test run, mirroring the real-world firmware update logic.
This flow ensures that the host-side representation of the bootloader logic accurately prevents the installation of corrupted firmware.
Sources: host/test/dfu.test.ts:13-22, host/src/firmware/bootloader/dfu.ts:25-50
Type Definitions for Testing
Because the project uses the native Node.js test runner with TypeScript, custom type definitions are provided in host/types/node-test.d.ts to support the describe and it blocks, as well as the strict assertion methods.
| Interface/Function | Description |
|---|---|
describe(name, fn) | Groups related tests together. |
it(name, fn) | Defines an individual test case (supports async). |
assert.strictEqual | Validates that actual and expected values are identical. |
assert.ok | Validates that a value is truthy. |
Sources: host/types/node-test.d.ts:1-17
The testing methodology in OpenAwair serves as a contract-first approach, where host-side abstractions define the expected behavior of the embedded firmware, ensuring stability for future C/C++ development.