Skip to content

Commit 97fbc86

Browse files
committed
Added tests for GATT services
1 parent b88b7ac commit 97fbc86

File tree

4 files changed

+88
-49
lines changed

4 files changed

+88
-49
lines changed

.github/workflows/python-package.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
- name: Install dependencies
2828
run: |
2929
python -m pip install --upgrade pip
30-
python -m pip install flake8 pytest pytest-cov
30+
python -m pip install flake8 pytest pytest-cov pytest-asyncio
3131
python -m pip install -e .
3232
- name: Lint with flake8
3333
run: |

atmotube/__init__.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
from .gatt_notify import (InvalidAtmoTubeService,
2-
start_gatt_notifications,
3-
get_available_characteristics)
1+
from .gatt import (InvalidAtmoTubeService,
2+
gatt_notify,
3+
start_gatt_notifications,
4+
get_available_characteristics)
45
from .packets import (InvalidByteData,
56
AtmoTubePacket,
67
StatusPacket,

tests/test_gatt_services.py

Lines changed: 83 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,102 @@
1-
from unittest.mock import Mock, patch
1+
import pytest
2+
from unittest.mock import ANY, AsyncMock, Mock
3+
from bleak import BleakClient
24

35
from atmotube import (
46
AtmoTube_Service_UUID,
57
AtmoTube_PRO_UUID,
8+
StatusPacket,
9+
SPS30Packet,
10+
BME280Packet,
11+
SGPC3Packet,
612
InvalidAtmoTubeService,
7-
get_available_characteristics)
13+
get_available_characteristics,
14+
gatt_notify)
815

9-
from atmotube.gatt_notify import ALL_PACKETS
16+
ALL_PACKETS = [(AtmoTube_PRO_UUID.STATUS, StatusPacket),
17+
(AtmoTube_PRO_UUID.SPS30, SPS30Packet),
18+
(AtmoTube_PRO_UUID.BME280, BME280Packet),
19+
(AtmoTube_PRO_UUID.SGPC3, SGPC3Packet)]
1020

1121

1222
def test_get_available_characteristics_all():
13-
with patch("bleak.BleakClient", new_callable=Mock) as MockClient:
14-
mock_client = MockClient.return_value
15-
mock_client.services.get_service.return_value = Mock(
16-
uuid=AtmoTube_Service_UUID.PRO,
17-
characteristics=[
18-
Mock(uuid=AtmoTube_PRO_UUID.SGPC3),
19-
Mock(uuid=AtmoTube_PRO_UUID.BME280),
20-
Mock(uuid=AtmoTube_PRO_UUID.STATUS),
21-
Mock(uuid=AtmoTube_PRO_UUID.SPS30),
22-
]
23-
)
23+
client = Mock(spec=BleakClient)
24+
client.services.get_service.return_value = Mock(
25+
uuid=AtmoTube_Service_UUID.PRO,
26+
characteristics=[
27+
Mock(uuid=AtmoTube_PRO_UUID.SGPC3),
28+
Mock(uuid=AtmoTube_PRO_UUID.BME280),
29+
Mock(uuid=AtmoTube_PRO_UUID.STATUS),
30+
Mock(uuid=AtmoTube_PRO_UUID.SPS30),
31+
]
32+
)
2433

25-
# Call the function
26-
packet_list = get_available_characteristics(mock_client)
34+
# Call the function
35+
packet_list = get_available_characteristics(client)
2736

28-
# Assertions
29-
assert packet_list == ALL_PACKETS
37+
# Assertions
38+
assert packet_list == ALL_PACKETS
3039

3140

3241
def test_get_available_characteristics_no_pm():
33-
with patch("bleak.BleakClient", new_callable=Mock) as MockClient:
34-
mock_client = MockClient.return_value
35-
mock_client.services.get_service.return_value = Mock(
36-
uuid=AtmoTube_Service_UUID.PRO,
37-
characteristics=[
38-
Mock(uuid=AtmoTube_PRO_UUID.SGPC3),
39-
Mock(uuid=AtmoTube_PRO_UUID.BME280),
40-
Mock(uuid=AtmoTube_PRO_UUID.STATUS),
41-
]
42-
)
42+
client = Mock(spec=BleakClient)
43+
client.services.get_service.return_value = Mock(
44+
uuid=AtmoTube_Service_UUID.PRO,
45+
characteristics=[
46+
Mock(uuid=AtmoTube_PRO_UUID.SGPC3),
47+
Mock(uuid=AtmoTube_PRO_UUID.BME280),
48+
Mock(uuid=AtmoTube_PRO_UUID.STATUS),
49+
]
50+
)
4351

44-
# Call the function
45-
packet_list = get_available_characteristics(mock_client)
52+
# Call the function
53+
packet_list = get_available_characteristics(client)
4654

47-
# Assertions
48-
assert packet_list == [packet for packet in ALL_PACKETS
49-
if packet[0] != AtmoTube_PRO_UUID.SPS30]
55+
# Assertions
56+
assert packet_list == [packet for packet in ALL_PACKETS
57+
if packet[0] != AtmoTube_PRO_UUID.SPS30]
5058

5159

5260
def test_get_available_characteristics_invalid_service():
53-
with patch("bleak.BleakClient", new_callable=Mock) as MockClient:
54-
mock_client = MockClient.return_value
55-
mock_client.services.get_service.return_value = None
56-
57-
# Call the function and expect an exception
58-
try:
59-
get_available_characteristics(mock_client)
60-
except Exception as e:
61-
assert isinstance(e, InvalidAtmoTubeService)
62-
assert str(e) == "AtmoTube Pro service not found"
63-
else:
64-
assert False, "Expected exception was not raised"
61+
client = Mock(spec=BleakClient)
62+
client.services.get_service.return_value = None
63+
64+
# Call the function and expect an exception
65+
try:
66+
get_available_characteristics(client)
67+
except Exception as e:
68+
assert isinstance(e, InvalidAtmoTubeService)
69+
assert str(e) == "AtmoTube Pro service not found"
70+
else:
71+
assert False, "Expected exception was not raised"
72+
73+
74+
class MockPacket:
75+
def __init__(self, data):
76+
self.data = data
77+
78+
79+
@pytest.mark.asyncio
80+
async def test_gatt_notify_async_callback():
81+
uuid = "example-uuid"
82+
client = AsyncMock(spec=BleakClient)
83+
callback = AsyncMock()
84+
85+
# Call gatt_notify, and await the returned task
86+
task = gatt_notify(client, uuid, MockPacket, callback)
87+
await task
88+
89+
# Assert that start_notify was called with the uuid and something tbd
90+
client.start_notify.assert_called_once_with(uuid, ANY)
91+
92+
# Dummy notification being sent
93+
packet_callback = client.start_notify.call_args[0][1]
94+
notification_data = bytearray([0, 1, 2, 3])
95+
await packet_callback(None, notification_data)
96+
97+
# Assert that the original callback is called with one argument
98+
# and that argument is of the correct instance and holds the data
99+
callback.assert_awaited_once()
100+
callback.assert_called_once_with(ANY)
101+
assert isinstance(callback.call_args.args[0], MockPacket)
102+
assert callback.call_args.args[0].data == notification_data

0 commit comments

Comments
 (0)