我正在使用Bleak来发现并连接到最近的蓝牙低功耗(BLE)设备,并且我正在编写单元测试(使用pytest)。
我是Python测试的新手,我不知道如何处理这些补丁/模拟才能使其在async
函数上正常工作。
我不知道我应该使用实际功能,还是对默认功能应用补丁以使测试无需BLE加密狗即可执行。
以下是代码示例(对discover.py的改进):
def list(op_sys: str) -> list:
"""list BLE devices
Returns:
list: status & list or error message
"""
import asyncio, platform
from bleak import discover
async def run() -> list:
"""discover BLE devices
Returns:
list: status & list or error message
"""
BLElist = []
try:
devices = await discover()
for d in devices:
print("'%s'" % d.name) # list devices
BLElist.append(d.name)
return 'success', BLElist
except:
return 'error', 'You don\'t have any BLE dongle.'
# linux = 3.6, windows = 3.7, need a new loop to work
if op_sys == "Windows":
asyncio.set_event_loop(asyncio.new_event_loop())
loop = asyncio.get_event_loop()
return loop.run_until_complete(run())
我想知道是否应该重写该函数以将run()
部分移出并进行模拟。
答案 0 :(得分:2)
外部函数fromdata.append('typeofatrocity', typeofatrocity)
不异步,因为它对list(op_sys) -> list
进行了调用。
以便像任何同步python函数一样可以对其进行单元测试。
如果要对异步函数(例如内部函数loop.run_until_complete
)进行单元测试,请在此处查看:https://pypi.org/project/asynctest/。
答案 1 :(得分:0)
因此,使用Freek的help,我知道我想模拟bleak.discover
,这是我的做法:
我使用Ivan的this anwser找到了解决方案。
这是我的考试:
import os, asyncio
from unittest.mock import Mock
from app.functions.ble import ble
class BLE:
def __init__(self, name):
self.name = name
# code of Ivan, thank you Ivan!
def async_return(result):
f = asyncio.Future()
f.set_result(result)
return f
def test_list(monkeypatch):
mock_discover = Mock(return_value=async_return([BLE("T-000001"), BLE("T-000002"), BLE("T-000003")]))
monkeypatch.setattr('bleak.discover', mock_discover)
list_BLE = ble.list("Linux")
mock_discover.assert_called_once()
assert list_BLE[0] == 'success'
assert list_BLE[1][0] == "T-000001"
这是测试结果:
tests/test_ble.py::test_list 'T-000001'
'T-000002'
'T-000003'
PASSED
=== 1 passed in 0.09 seconds ===
编辑:推荐精美代码:
from unittest import TestCase
from unittest.mock import patch
import os, asyncio
from app.functions.ble import ble
class DeviceDiscoveryTest(TestCase):
@staticmethod
def __async_return(result):
f = asyncio.Future()
f.set_result(result)
return f
@classmethod
def mocked_discover(cls):
return cls.__async_return([BLE("T-000001"), BLE("T-000002"), BLE("T-000003")])
@patch('bleak.discocver', new=DeviceDiscoveryTest.mocked_discover)
def test_discover_devices(self):
list_BLE = ble.list("Linux")
self.assertEquals('success', list_BLE[0])
....