Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clocked test case #83

Open
lromor opened this issue Apr 13, 2018 · 2 comments
Open

Clocked test case #83

lromor opened this issue Apr 13, 2018 · 2 comments

Comments

@lromor
Copy link

lromor commented Apr 13, 2018

Hello,
how would you achieve something similar to this:
https://asynctest.readthedocs.io/en/latest/asynctest.case.html#asynctest.ClockedTestCase

with pytest asyncio?

-l

@albertodonato
Copy link

albertodonato commented Dec 22, 2018

I had the same need, I'm using something like this, which is a straight copy of ClockedTestCase logic:

@pytest.fixture
async def advance_time(event_loop):

    class Clocker:

        time: float = 0

        def __init__(self, loop: asyncio.BaseEventLoop):
            self.loop = loop
            self.loop.time = lambda: self.time

        async def advance(self, seconds: float):
            if seconds < 0:
                raise ValueError('Advance time must not be negative')
            await self._drain_loop()

            target_time = self.time + seconds
            while True:
                next_time = self._next_scheduled()
                if next_time is None or next_time > target_time:
                    break

                self.time = next_time
                await self._drain_loop()

            self.time = target_time
            await self._drain_loop()

        def _next_scheduled(self):
            try:
                return self.loop._scheduled[0]._when
            except IndexError:
                return None

        async def _drain_loop(self):
            while True:
                next_time = self._next_scheduled()
                if (not self.loop._ready
                        and (next_time is None or next_time > self.time)):
                    break
                await asyncio.sleep(0)

    yield Clocker(event_loop).advance

in tests you can use:

@pytest.mark.asyncio
async def test_foo(advance_time):
    await do_stuff()
    await advance_time(2)
    await more_stuff()

@albertodonato
Copy link

It would be nice to have something like this builtin

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants