Skip to content

Commit cfc0070

Browse files
committed
test: extract connected client to a fixture
style: fix formatting of tests refactor: extract variables for mock data used in mqtt tests style: fix lint errors in tests
1 parent 8e996b8 commit cfc0070

File tree

4 files changed

+43
-34
lines changed

4 files changed

+43
-34
lines changed

tests/conftest.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import io
22
import logging
3-
import queue
43
import re
54
from collections.abc import Callable, Generator
5+
from queue import Queue
66
from typing import Any
77
from unittest.mock import Mock, patch
88

@@ -63,29 +63,29 @@ def handle_socket_send(self, client_request: bytes) -> int:
6363

6464

6565
@pytest.fixture(name="received_requests")
66-
def received_requests_fixture() -> queue.Queue[bytes]:
66+
def received_requests_fixture() -> Queue[bytes]:
6767
"""Fixture that provides access to the received requests."""
68-
return queue.Queue()
68+
return Queue()
6969

7070

7171
@pytest.fixture(name="response_queue")
72-
def response_queue_fixture() -> queue.Queue[bytes]:
72+
def response_queue_fixture() -> Generator[Queue[bytes], None, None]:
7373
"""Fixture that provides access to the received requests."""
74-
return queue.Queue()
74+
response_queue: Queue[bytes] = Queue()
75+
yield response_queue
76+
assert response_queue.empty(), "Not all fake responses were consumed"
7577

7678

7779
@pytest.fixture(name="request_handler")
78-
def request_handler_fixture(
79-
received_requests: queue.Queue[bytes], response_queue: queue.Queue[bytes]
80-
) -> RequestHandler:
80+
def request_handler_fixture(received_requests: Queue[bytes], response_queue: Queue[bytes]) -> RequestHandler:
8181
"""Fixture records incoming requests and replies with responses from the queue."""
8282

8383
def handle_request(client_request: bytes) -> bytes | None:
8484
"""Handle an incoming request from the client."""
8585
received_requests.put(client_request)
8686

8787
# Insert a prepared response into the response buffer
88-
if response_queue.qsize() > 0:
88+
if not response_queue.empty():
8989
return response_queue.get()
9090
return None
9191

tests/mock_data.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
"""Mock data for Roborock tests."""
2+
3+
import hashlib
4+
25
# All data is based on a U.S. customer with a Roborock S7 MaxV Ultra
36
USER_EMAIL = "user@domain.com"
47

58
BASE_URL = "https://usiot.roborock.com"
69

10+
USER_ID = "user123"
11+
K_VALUE = "domain123"
712
USER_DATA = {
813
"uid": 123456,
914
"tokentype": "token_type",
@@ -14,10 +19,10 @@
1419
"country": "US",
1520
"nickname": "user_nickname",
1621
"rriot": {
17-
"u": "user123",
22+
"u": USER_ID,
1823
"s": "pass123",
1924
"h": "unknown123",
20-
"k": "domain123",
25+
"k": K_VALUE,
2126
"r": {
2227
"r": "US",
2328
"a": "https://api-us.roborock.com",
@@ -29,6 +34,7 @@
2934
"avatarurl": "https://files.roborock.com/iottest/default_avatar.png",
3035
}
3136
LOCAL_KEY = "key123"
37+
PRODUCT_ID = "product-id-123"
3238
HOME_DATA_RAW = {
3339
"id": 123456,
3440
"name": "My Home",
@@ -37,7 +43,7 @@
3743
"geoName": None,
3844
"products": [
3945
{
40-
"id": "abc123",
46+
"id": PRODUCT_ID,
4147
"name": "Roborock S7 MaxV",
4248
"code": "a27",
4349
"model": "roborock.vacuum.a27",
@@ -339,5 +345,5 @@
339345
}
340346

341347
GET_CODE_RESPONSE = {"code": 200, "msg": "success", "data": None}
342-
343-
MQTT_PUBLISH_TOPIC = "rr/m/o/user123/6ac2e6f8/abc123"
348+
HASHED_USER = hashlib.md5((USER_ID + ":" + K_VALUE).encode()).hexdigest()[2:10]
349+
MQTT_PUBLISH_TOPIC = f"rr/m/o/{USER_ID}/{HASHED_USER}/{PRODUCT_ID}"

tests/test_api.py

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import json
2+
from collections.abc import AsyncGenerator
23
from queue import Queue
34
from typing import Any
45
from unittest.mock import patch
@@ -145,19 +146,28 @@ async def test_get_prop():
145146
assert props.dock_summary.dust_collection_mode is not None
146147

147148

148-
async def test_async_connect(
149-
received_requests: Queue, response_queue: Queue, mqtt_client: RoborockMqttClientV1
150-
) -> None:
151-
"""Test connecting to the MQTT broker."""
152-
149+
@pytest.fixture(name="connected_mqtt_client")
150+
async def connected_mqtt_client_fixture(
151+
response_queue: Queue, mqtt_client: RoborockMqttClientV1
152+
) -> AsyncGenerator[RoborockMqttClientV1, None]:
153153
response_queue.put(mqtt_packet.gen_connack(rc=0, flags=2))
154154
response_queue.put(mqtt_packet.gen_suback(1, 0))
155-
156155
await mqtt_client.async_connect()
157-
assert mqtt_client.is_connected()
156+
yield mqtt_client
157+
if mqtt_client.is_connected():
158+
await mqtt_client.async_disconnect()
158159

159-
await mqtt_client.async_disconnect()
160-
assert not mqtt_client.is_connected()
160+
161+
async def test_async_connect(received_requests: Queue, connected_mqtt_client: RoborockMqttClientV1) -> None:
162+
"""Test connecting to the MQTT broker."""
163+
164+
assert connected_mqtt_client.is_connected()
165+
# Connecting again is a no-op
166+
await connected_mqtt_client.async_connect()
167+
assert connected_mqtt_client.is_connected()
168+
169+
await connected_mqtt_client.async_disconnect()
170+
assert not connected_mqtt_client.is_connected()
161171

162172
# Broker received a connect and subscribe. Disconnect packet is not
163173
# guaranteed to be captured by the time the async_disconnect returns
@@ -198,15 +208,10 @@ def build_rpc_response(message: dict[str, Any]) -> bytes:
198208
async def test_get_room_mapping(
199209
received_requests: Queue,
200210
response_queue: Queue,
201-
mqtt_client: RoborockMqttClientV1,
211+
connected_mqtt_client: RoborockMqttClientV1,
202212
) -> None:
203213
"""Test sending an arbitrary MQTT message and parsing the response."""
204214

205-
response_queue.put(mqtt_packet.gen_connack(rc=0, flags=2))
206-
response_queue.put(mqtt_packet.gen_suback(1, 0))
207-
await mqtt_client.async_connect()
208-
assert mqtt_client.is_connected()
209-
210215
test_request_id = 5050
211216
message = build_rpc_response(
212217
{
@@ -217,11 +222,9 @@ async def test_get_room_mapping(
217222
response_queue.put(mqtt_packet.gen_publish(MQTT_PUBLISH_TOPIC, payload=message))
218223

219224
with patch("roborock.version_1_apis.roborock_client_v1.get_next_int", return_value=test_request_id):
220-
room_mapping = await mqtt_client.get_room_mapping()
225+
room_mapping = await connected_mqtt_client.get_room_mapping()
221226

222227
assert room_mapping == [
223228
RoomMapping(segment_id=16, iot_id="2362048"),
224229
RoomMapping(segment_id=17, iot_id="2362044"),
225230
]
226-
227-
await mqtt_client.async_disconnect()

tests/test_containers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
RoborockStateCode,
1111
)
1212

13-
from .mock_data import CLEAN_RECORD, CLEAN_SUMMARY, CONSUMABLE, DND_TIMER, HOME_DATA_RAW, STATUS, USER_DATA
13+
from .mock_data import CLEAN_RECORD, CLEAN_SUMMARY, CONSUMABLE, DND_TIMER, HOME_DATA_RAW, PRODUCT_ID, STATUS, USER_DATA
1414

1515

1616
def test_user_data():
@@ -43,7 +43,7 @@ def test_home_data():
4343
assert hd.lat is None
4444
assert hd.geo_name is None
4545
product = hd.products[0]
46-
assert product.id == "abc123"
46+
assert product.id == PRODUCT_ID
4747
assert product.name == "Roborock S7 MaxV"
4848
assert product.code == "a27"
4949
assert product.model == "roborock.vacuum.a27"

0 commit comments

Comments
 (0)