Development
Tests
Note: Running the tests (successfully) requires that
you connected a STU to your test system,
at least one sensor device (e.g. STH) is available
the sensor device has support for changing the sensor configuration (mapping sensor channels to measurement channels)
In the text below we assume that you installed
To run the tests run the following command:
just test
Tests are grouped with pytest markers:
hardware: tests that need the hardware described above. Run all other tests withjust test-no-hardware.mqtt: tests that need an MQTT broker. They are skipped, unless you set the environment variableTEST_MQTT_BROKER(host name of the broker).TEST_MQTT_PORT(default: 1883),TEST_MQTT_USERNAMEandTEST_MQTT_PASSWORDare optional. The tests publish to topics belowicodaq-test/<random ID>and remove what they published. Run only these tests withjust test-mqtt, for example with a temporary Mosquitto broker:docker run -d --rm --name test-mosquitto -p 127.0.0.1:18883:1883 eclipse-mosquitto:2 \ sh -c 'printf "listener 1883\nallow_anonymous true\n" > /tmp/m.conf && exec mosquitto -c /tmp/m.conf' TEST_MQTT_BROKER=127.0.0.1 TEST_MQTT_PORT=18883 just test-mqtt docker stop test-mosquitto
Guidelines
These guidelines are a work-in-progress and aim to explain development decisions and support consistency.
WebSockets
WebSockets are only used to send data from ICOapi to clients (state, measurement data, logs), never to receive data. Everything a client wants to tell ICOapi (commands, requests for data) goes through the REST API. Clients must not send messages over a WebSocket; the /state WebSocket ignores everything a client sends.
This keeps a WebSocket interchangeable with other transports, such as MQTT, for publishing the same updates.
Logging
The application is set up to log everything. This is how the logging is set up.
Guidelines
Log only after success
Don’t log intent, like “Creating user…” or “Initializing widget…” unless it’s for debugging.
Do log outcomes, like “User created successfully.” — but only after the operation completes without error.
Avoid logging in constructors unless they cannot fail
Prefer logging in methods that complete the actual operation,
or use a factory method to wrap creation and success logging.
Levels
Action |
Log Level |
Description (taken from Python docs) |
|---|---|---|
Starting a process / intention |
|
Detailed information for diagnosing problems. Mostly useful for developers. |
Successfully completed action |
|
For confirming that things are working as expected. |
Recoverable error / edge case |
|
Indicates something unexpected happened or could cause problems later. |
Expected failure / validation |
|
Used for serious problems that caused a function to fail. |
Critical Failure / unrecoverable |
|
For very serious errors. Indicates a critical condition — program may abort. |
Unexpected exception (with trace) |
|
Serious errors, but the exception was caught. |
Release
Note: In the text below we assume that you want to release version <VERSION> of the package. Please just replace this version number with the version that you want to release (e.g. 0.2.0).
Make sure that all the checks and tests work correctly locally
just
Make sure all workflows of the CI system work correctly
Release a new version on PyPI:
just release <VERSION>
Open the release notes for the latest version and create a new release
Paste them into the main text of the release web page
Insert the version number into the tag field
For the release title use “Version
”, where <VERSION>specifies the version number (e.g. “Version 0.2”)Click on “Publish Release”
Note: Alternatively you can also use the
ghcommand:gh release create
to create the release notes.