3

I need to call a task every second (say) to poll some sensor data on a piece of hardware. In the unit test, all I want to do, is to check that the right methods are called and that errors (such as sensor has blown up or vanished) do get caught.

Here is a toy example that mimics the real code:

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

As expected, running this will block forever.

How can I cancel the ook task so that the unit test does not block?

A work around would be to split the loop into another function and define it as no testable. I want to avoid doing that. Note also that messing with func (to call loop.close() or some such) does not work either as it is there just so the toy example test can assert something.

2 Answers 2

4

As it stands, the way you've designed the ook method is the cause of your issue.

Due to the ook method, it will always be a blocking operation. I assume, since you're using asyncio you want ook to be non-blocking on the main thread?

If thats the case, asyncio actually comes with an event loop built in, see this comment for an example., which will run an task on another thread and gives you ways to control that task.

Documentation/samples for the event loop are here

Sign up to request clarification or add additional context in comments.

Comments

3

Based off duFF's answer, here is the fixed toy code:

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()

When run:

; 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 ===========================

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.