pytest-dev / pytest-dev/pytest-asyncio
Is there a way to fail a test if an explicitly created background task fails after yielding from the fixture that created it?
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 1.7k
- Forks
- 207
- Avg merge
- 5h 35m
- Merged PRs (30d)
- 9
Description
I'll start with an example to provide some context:
import asyncio
import contextlib
import itertools
import pytest
class Consumer:
def __init__(self, queue: asyncio.Queue):
self._queue = queue
async def run(self):
for i in itertools.count(0):
item = await self._queue.get()
print(item)
if i == 3:
raise ValueError('oups')
self._queue.task_done()
@pytest.fixture
async def queue() -> asyncio.Queue:
return asyncio.Queue()
@pytest.fixture
async def consumer_service(queue):
consumer = Consumer(queue)
background_task = asyncio.create_task(consumer.run())
yield
background_task.cancel()
with contextlib.suppress(asyncio.CancelledError):
await run_task
@pytest.mark.asyncio
@pytest.mark.usefixtures('consumer_service')
async def test_consumer_consumes(queue: asyncio.Queue):
queue.put_nowait('I')
queue.put_nowait('Will')
queue.put_nowait('Not')
queue.put_nowait('Hang')
await queue.join()
Here, the consumer service fixture will create a background task that runs the consumer's loop. When processing the last item in the queue, a value error is raised and the background task finishes with an exception before marking the last item as done. In this state, the test will hang and there will be no indication that something went astray.
Ideally, there would be some way to react to the background task failing by canceling and failing the test but I have not seen a way to do it. The closest I got to a solution was to attach a done callback to the background task and check for an exception there but I haven't come across an API that would allow me to recover from this or a way to signal the error (without it being captured by pytest).
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the asyncio fixture and background-task example in this issue, focusing on how pytest-asyncio handles tasks created before a fixture yields. Investigate whether a task exception can cancel and fail the test instead of leaving queue.join() hanging. Done means the shown failure is reported by pytest without requiring an ad hoc callback.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- testing-qa
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100