如何执行异步功能的单元测试?

时间:2019-06-18 07:33:32

标签: python unit-testing bluetooth-lowenergy pytest python-asyncio

我正在使用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()部分移出并进行模拟。

2 个答案:

答案 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])
        ....
相关问题