-
Notifications
You must be signed in to change notification settings - Fork 162
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
Clarify docs about requesting the event_loop
fixture
#964
Comments
The use of event_loop is deprecated. We should adjust the docs to reflect that. |
Slowly getting back here. The thing why I'm asking is that currently we do something like: def some_fixture(event_loop):
# do some sync stuff etc...
# then trigger async actions:
event_loop.run_until_complete(...) Similar pattern is not possible with asyncio.get_running_loop() because:
Being able to run invocations in the event loop in a sync function is convenient, as we don't have 100% async codebase, and tests are mostly written in sync. Do you see the use case here @seifertm? Is the advice to convert the usages to async and then asyncio.to_thread() to sync parts, instead? |
The migration guide suggests converting such tests to async tests and use get_running_loop inside the async test. Following your example: @pytest_asyncio.fixture()
async def some_fixture():
# do some sync stuff etc...
# then trigger async actions:
event_loop = asyncio.get_running_loop()
event_loop.run_until_complete(...) You could possibly even skip @pytest_asyncio.fixture()
async def some_fixture():
# do some sync stuff etc...
# then trigger async actions:
await ... @tuukkamustonen Do any of those approaches work for your code base? |
@seifertm Hey hey, sorry I totally missed your response (in December!) The problem was that earlier it was possible to inject the loop into a sync test, e.g.: def test_something(event_loop):
event_loop.run_until_complete(...) But with the fixture deprecated, you're no longer supposed to do that. Unless I define my own fixture: @pytest.fixture
async def event_loop():
return asyncio.get_running_loop()
def test_something(event_loop):
event_loop.run_until_complete(...) Didn't try that, but I guess it would work? Or, do something like: class TestSomeClass:
loop: asyncio.AbstractEventLoop
@pytext.fixture(autouse=True)
def init(self):
self.loop = asyncio.get_running_loop()
def test_something(self):
self.loop.run_until_complete(...) How do you see those? Bad? Naughty? It's convenient to access the loop from sync test method - even with async codebases, tests may often by written as sync (and FastAPI et al perfectly allow that). |
@tuukkamustonen would it be possible for you to replace
with async def test_something():
event_loop = asyncio.get_running_loop( )
event_loop.run_until_complete(...) or async def test_something():
await … ? My understanding is that these are functionally equivalent and they would allow pytest-asyncio to proceed with the event_loop fixture deprecation. |
No, that converts the whole test as The tests might be doing a lot of things, ie. calling DB, reading network, file system, etc and we'd need to convert everything to async. Don't want to take that effort / see the benefit. Of course, sync IO works in async context, it just blocks the loop. On a usual application that would be disastrous, I don't know what the effect in this case would be? Are async tests still run one-by-one, ie. not concurrently, so that blocking the loop would actually do no harm? |
Your benefit is only indirect. Getting rid of event_loop allows pytest-asyncio to adjust to recent asyncio development and simplify its code base. This will hopefully result in more contributions and/or faster development.
Pytest-asyncio still runs its tests one-by-one. This is a constraint by pytest itself. The asyncio plugin merely tries to make it easier to test async code without having to use asyncio.Runner or asyncio.get_event_loop directly. There was an idea to provide automatic code rewriting for such changes using libCST. It's definitely an option to include such a rewriter in pytest-asyncio, but someone would have to contribute it. It's only worth it for large test suites, I guess. |
Hey, just for clarity's sake, I'm not arguing As discussed, there are two workarounds:
These could have been explained/suggested in the migration docs, though both are a bit hacky, so I understand you don't probably want to give such suggestions 😄 Well, at least they're now documented here, in this ticket.
Honestly, that (complexity of it) sounds like a trap. Could be a separate (and more generic) tool, if someone needs that. Surely not part of (I think we can conclude this discussion - thanks for the help and your work on the lib in general 🙏🏻) |
https://pytest-asyncio.readthedocs.io/en/latest/reference/fixtures/index.html#event-loop suggests that it's fine to grab
event_loop
fixture in a non-async function.0.21+ migration guide in https://pytest-asyncio.readthedocs.io/en/latest/how-to-guides/migrate_from_0_21.html suggests to convert all sync functions requesting the
event_loop
fixture into async functions, and then acquire the loop viaasyncio.get_running_loop()
.Which one is it, and what is the rationale of not depending on the
event_loop
fixture directly?The text was updated successfully, but these errors were encountered: