Python 在asyncio中测试永久运行的任务
我需要每秒调用一个任务(比如)来轮询硬件上的一些传感器数据。在单元测试中,我想做的就是检查是否调用了正确的方法,以及是否捕捉到错误(例如传感器爆炸或消失) 下面是一个模拟真实代码的玩具示例:Python 在asyncio中测试永久运行的任务,python,python-3.x,pytest,python-asyncio,Python,Python 3.x,Pytest,Python Asyncio,我需要每秒调用一个任务(比如)来轮询硬件上的一些传感器数据。在单元测试中,我想做的就是检查是否调用了正确的方法,以及是否捕捉到错误(例如传感器爆炸或消失) 下面是一个模拟真实代码的玩具示例: import pytest import asyncio import mock async def ook(func): while True: await asyncio.sleep(1) func() @pytest.mark.asyncio async
import pytest
import asyncio
import mock
async def ook(func):
while True:
await asyncio.sleep(1)
func()
@pytest.mark.asyncio
async def test_ook():
func = mock.Mock()
await ook(func)
assert func.called is True
正如所料,运行此命令将永远阻塞
如何取消ook
任务,使单元测试不会阻塞
解决方法是将循环拆分为另一个函数,并将其定义为不可测试。我想避免那样做。另外请注意,混用
func
(调用loop.close()
或类似的方法)也不起作用,因为它只是为了让玩具示例测试能够断言某些东西。就目前而言,您设计ook
方法的方式是问题的原因
由于采用了ook
方法,它将始终是一个阻塞操作。我假设,既然您使用的是asyncio
,您希望ook
在主线程上是非阻塞的
如果是这种情况,asyncio
实际上内置了一个事件循环,请参阅,它将在另一个线程上运行任务,并为您提供控制该任务的方法
事件循环的文档/示例基于的,以下是固定的玩具代码:
import pytest
import asyncio
import mock
async def ook(func):
await asyncio.sleep(1)
func()
return asyncio.ensure_future(ook(func))
@pytest.mark.asyncio
async def test_ook():
func = mock.Mock()
task = await ook(func)
assert func.called is True
task.cancel()
运行时:
; py.test tests/ook.py
============================= test session starts ==============================
platform linux -- Python 3.6.1, pytest-3.1.3, py-1.4.34, pluggy-0.4.0
run-last-failure: rerun last 4 failures first
rootdir: /home/usr/blah, inifile: setup.cfg
plugins: xvfb-1.0.0, xdist-1.18.2, colordots-0.1, asyncio-0.6.0
collected 1 item s
ook.py::test_ook PASSED
---------- generated xml file: /home/yann/repos/raiju/unit_tests.xml -----------
============================== 0 tests deselected ==============================
=========================== 1 passed in 0.02 seconds ===========================