Testing Helpers¶
chumicro_wifi.testing provides FakeWifi and FakeWifiAdapter so your tests can drive connect, drop, and reconnect scenarios deterministically: no real radio, no real network, no real time. The fakes stay on the host: chumicro-deploy reads the test-support marker at the top of the module and leaves it out of every device bundle it builds.
FakeWifi¶
A WifiService wrapping a FakeWifiAdapter with the test hooks exposed directly on the wrapper. Use this when you want a drop-in WifiService your code-under-test treats like the real thing:
from chumicro_wifi.testing import FakeWifi
from chumicro_timing.testing import FakeTicks
def test_my_service_waits_for_wifi():
ticks = FakeTicks()
wifi = FakeWifi(ticks)
wifi.set_connect_outcome(True)
my_service = MyService(wifi=wifi)
my_service.start()
ticks.advance(0)
wifi.tick() # one runner-style check + handle
assert wifi.state == "connected"
assert my_service.ready
FakeWifi ships with sensible defaults (ssid="testnet", password="password", short reconnect backoffs). Pass config= a custom WifiConfig if your test needs different settings.
Test hooks¶
The hooks below live on FakeWifiAdapter and are forwarded to FakeWifi for ergonomic test code:
| Hook | What it does |
|---|---|
set_connect_outcome(True) |
Next connect() succeeds. |
set_connect_outcome(False) |
Next connect() returns a clean refusal. |
set_connect_outcome(OSError) |
Next connect() raises the named exception class. |
set_connect_outcomes([True, False, True]) |
Queue a one-shot sequence of outcomes; the default takes over after the queue drains. |
drop_link() |
Simulates a link-down event: the next is_linked() returns False, which sends the service into its reconnect path. |
restore_link() |
Simulates the access point coming back on its own, with no connect() call. |
calls |
List of recorded adapter calls (("configure", config), ("connect", config)). Assert on this to verify call ordering. |
Simulating a reconnect¶
Use drop_link() plus FakeTicks.advance() to step through a real reconnect cycle:
def test_reconnect_after_link_drop():
ticks = FakeTicks()
wifi = FakeWifi(ticks)
wifi.set_connect_outcome(True)
wifi.tick() # connects
assert wifi.state == "connected"
wifi.drop_link() # simulate link-down
wifi.tick() # service notices, enters RECONNECTING
ticks.advance(200) # past the first backoff window
wifi.tick() # reconnect attempt fires
assert wifi.state == "connected"
FakeWifiAdapter (lower level)¶
When you need to compose your own service shape (a test that wires FakeWifiAdapter into a real WifiService to check the supervisor's behavior, for example), use the adapter directly:
from chumicro_wifi import WifiConfig, WifiService
from chumicro_wifi.testing import FakeWifiAdapter
from chumicro_timing.testing import FakeTicks
def test_supervisor_handles_exception_during_connect():
ticks = FakeTicks()
adapter = FakeWifiAdapter()
adapter.set_connect_outcome(OSError) # exception class to raise
service = WifiService(
WifiConfig(ssid="lab", password="lab-pw"),
adapter=adapter,
ticks=ticks,
)
service.handle(0)
# The exception is captured, not propagated: the service stays
# in CONNECTING with a retry scheduled.
assert isinstance(service.last_error, OSError)
assert service.state == "connecting"
Using these fakes in your own tests¶
Install chumicro-wifi and import the fakes straight into your test suite:
Project convention: libraries that expose injectable services ship their own test fakes alongside the production code.
API Reference¶
chumicro_wifi.testing
¶
Test helpers for libraries that depend on chumicro-wifi.
Hosts the test fakes :class:FakeWifi and :class:FakeWifiAdapter.
FakeWifiAdapter
¶
Bases: WifiAdapter
In-memory adapter with explicit hooks for test scenarios.
configured_with
property
¶
The :class:WifiConfig last passed to :meth:configure.
set_connect_outcome(outcome)
¶
Control what the next :meth:connect call returns or raises.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
outcome
|
object
|
|
required |
set_connect_outcomes(outcomes)
¶
Queue a one-shot sequence of outcomes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
outcomes
|
object
|
Iterable of outcome values consumed in order, then falls back to the default. |
required |
set_connect_blocks(blocks)
¶
Toggle the blocking (CP) vs non-blocking (MP) connect model.
set_deferred_link(*, link_after)
¶
Model a non-blocking join that links after link_after polls.
drop_link()
¶
Simulate a link-down event without disconnecting cleanly.
restore_link()
¶
Simulate the AP coming back on its own (no connect call).
FakeWifi
¶
Bases: WifiService
WifiService wrapping a :class:FakeWifiAdapter for tests.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ticks
|
object
|
A tick source, typically a :class: |
required |
config
|
WifiConfig | None
|
Optional :class: |
None
|
calls
property
¶
List of recorded adapter calls.
set_connect_outcome(outcome)
¶
Forward to the underlying :class:FakeWifiAdapter.
set_connect_outcomes(outcomes)
¶
Forward to the underlying :class:FakeWifiAdapter.
drop_link()
¶
Forward to the underlying :class:FakeWifiAdapter.
restore_link()
¶
Forward to the underlying :class:FakeWifiAdapter.
set_connect_blocks(blocks)
¶
Forward to the underlying :class:FakeWifiAdapter.
set_deferred_link(*, link_after)
¶
Forward to the underlying :class:FakeWifiAdapter.
tick()
¶
Run one runner-style check + handle cycle.