CodeRigor

GUIDED LESSON / 3 OF 6

Test a hysteresis band

Write the decision as a pure function and test both edges.

What moves through this step
  1. 01Input pair
  2. 02Validation
  3. 03Previous state
  4. 04New state

Keep the rule independent of the sensor

The same function runs in CPython for tests and in MicroPython on the board. It takes a reading and the previous state; it does not import a pin driver or read a clock.

Python
"""Shared CPython/MicroPython decision logic; temperatures are Celsius."""
def state_for(temperature, humidity, previous="unknown"):
    for value in (temperature, humidity):
        if isinstance(value, bool) or not isinstance(value, (int, float)) or value != value:
            return "unknown"
    if not (0 <= temperature <= 50 and 0 <= humidity <= 100):
        return "unknown"
    if temperature >= 28:
        return "warm"
    if temperature <= 26:
        return "ok"
    return previous if previous in ("ok", "warm") else "ok"

A boolean is an integer subtype in Python, but it is not a temperature reading in this interface. The explicit boolean rejection matters when a record is accidentally shaped incorrectly. NaN is rejected before comparisons; infinities fail the range check.

Replay the important transition

Python
from policy import state_for
state = "unknown"
for temperature in [25, 27, 28, 27, 26]:
    state = state_for(temperature, 50, state)
    print(temperature, state)

Expect ok, ok, warm, warm, ok. Test the exact edges, not only a comfortable midpoint. After None, status should become unknown; the next 27 °C reading starts from that explicit state.

Try it

Change the warm threshold and return threshold together, keeping a gap between them. Add tests for the new exact boundaries before deploying. Avoid editing a separate copy of the policy in the firmware; copy the tested file to the board instead.