@@ -148,15 +148,15 @@ async def test_a():
148
148
)
149
149
150
150
151
- def test_asyncio_marker_fallbacks_to_configured_default_loop_scope_if_not_set (
151
+ def test_asyncio_marker_uses_marker_loop_scope_even_if_config_is_set (
152
152
pytester : Pytester ,
153
153
):
154
154
pytester .makeini (
155
155
dedent (
156
156
"""\
157
157
[pytest]
158
158
asyncio_default_fixture_loop_scope = function
159
- asyncio_default_test_loop_scope = session
159
+ asyncio_default_test_loop_scope = module
160
160
"""
161
161
)
162
162
)
@@ -175,6 +175,7 @@ async def session_loop_fixture():
175
175
global loop
176
176
loop = asyncio.get_running_loop()
177
177
178
+ @pytest.mark.asyncio(loop_scope="session")
178
179
async def test_a(session_loop_fixture):
179
180
global loop
180
181
assert asyncio.get_running_loop() is loop
@@ -186,56 +187,125 @@ async def test_a(session_loop_fixture):
186
187
result .assert_outcomes (passed = 1 )
187
188
188
189
189
- def test_asyncio_marker_uses_marker_loop_scope_even_if_config_is_set (
190
- pytester : Pytester ,
191
- ):
192
- pytester .makeini (
190
+ def test_uses_loop_factory_from_test (pytester : Pytester ):
191
+ pytester .makeini ("[pytest]\n asyncio_default_fixture_loop_scope = function" )
192
+ pytester .makepyfile (
193
193
dedent (
194
194
"""\
195
- [pytest]
196
- asyncio_default_fixture_loop_scope = function
197
- asyncio_default_test_loop_scope = module
195
+ import asyncio
196
+ import pytest_asyncio
197
+ import pytest
198
+
199
+ class CustomEventLoop(asyncio.SelectorEventLoop):
200
+ pass
201
+
202
+ @pytest_asyncio.fixture(loop_scope="module")
203
+ async def any_fixture():
204
+ assert type(asyncio.get_running_loop()) == CustomEventLoop
205
+
206
+ @pytest.mark.asyncio(loop_scope="module", loop_factory=CustomEventLoop)
207
+ async def test_set_loop_factory(any_fixture):
208
+ assert type(asyncio.get_running_loop()) == CustomEventLoop
198
209
"""
199
210
)
200
211
)
212
+ result = pytester .runpytest ("--asyncio-mode=strict" )
213
+ result .assert_outcomes (passed = 1 )
214
+
201
215
216
+ def test_uses_loop_factory_from_fixture (pytester : Pytester ):
217
+ pytester .makeini ("[pytest]\n asyncio_default_fixture_loop_scope = function" )
202
218
pytester .makepyfile (
203
219
dedent (
204
220
"""\
205
221
import asyncio
206
222
import pytest_asyncio
207
223
import pytest
208
224
209
- loop: asyncio.AbstractEventLoop
225
+ class CustomEventLoop(asyncio.SelectorEventLoop):
226
+ pass
210
227
211
- @pytest_asyncio.fixture(loop_scope="session", scope="session")
212
- async def session_loop_fixture():
213
- global loop
214
- loop = asyncio.get_running_loop()
228
+ @pytest_asyncio.fixture(loop_scope="module", loop_factory=CustomEventLoop)
229
+ async def any_fixture():
230
+ assert type(asyncio.get_running_loop()) == CustomEventLoop
215
231
216
- @pytest.mark.asyncio(loop_scope="session")
217
- async def test_a(session_loop_fixture):
218
- global loop
219
- assert asyncio.get_running_loop() is loop
232
+ @pytest.mark.asyncio(loop_scope="module")
233
+ async def test_set_loop_factory(any_fixture):
234
+ assert type(asyncio.get_running_loop()) == CustomEventLoop
220
235
"""
221
236
)
222
237
)
238
+ result = pytester .runpytest ("--asyncio-mode=strict" )
239
+ result .assert_outcomes (passed = 1 )
223
240
224
- result = pytester .runpytest ("--asyncio-mode=auto" )
241
+
242
+ def test_uses_loop_factory_from_transitive_fixture (pytester : Pytester ):
243
+ pytester .makeini ("[pytest]\n asyncio_default_fixture_loop_scope = function" )
244
+ pytester .makepyfile (
245
+ dedent (
246
+ """\
247
+ import asyncio
248
+ import pytest_asyncio
249
+ import pytest
250
+
251
+ class CustomEventLoop(asyncio.SelectorEventLoop):
252
+ pass
253
+
254
+ @pytest_asyncio.fixture(loop_scope="module", loop_factory=CustomEventLoop)
255
+ async def transitive_fixture():
256
+ assert type(asyncio.get_running_loop()) == CustomEventLoop
257
+
258
+ @pytest_asyncio.fixture(loop_scope="module")
259
+ async def any_fixture(transitive_fixture):
260
+ assert type(asyncio.get_running_loop()) == CustomEventLoop
261
+
262
+ @pytest.mark.asyncio(loop_scope="module")
263
+ async def test_set_loop_factory(any_fixture):
264
+ assert type(asyncio.get_running_loop()) == CustomEventLoop
265
+ """
266
+ )
267
+ )
268
+ result = pytester .runpytest ("--asyncio-mode=strict" )
225
269
result .assert_outcomes (passed = 1 )
226
270
227
271
228
- def test_asyncio_marker_event_loop_factories (pytester : Pytester ):
229
- pytester .makeini (
272
+ def test_conflicting_loop_factories_in_tests_raise_error (pytester : Pytester ):
273
+ pytester .makeini ("[pytest]\n asyncio_default_fixture_loop_scope = function" )
274
+ pytester .makepyfile (
230
275
dedent (
231
276
"""\
232
- [pytest]
233
- asyncio_default_fixture_loop_scope = function
234
- asyncio_default_test_loop_scope = module
277
+ import asyncio
278
+ import pytest_asyncio
279
+ import pytest
280
+
281
+ class CustomEventLoop(asyncio.SelectorEventLoop):
282
+ pass
283
+
284
+ class AnotherCustomEventLoop(asyncio.SelectorEventLoop):
285
+ pass
286
+
287
+ @pytest.mark.asyncio(loop_scope="module", loop_factory=CustomEventLoop)
288
+ async def test_with_custom_loop_factory():
289
+ ...
290
+
291
+ @pytest.mark.asyncio(
292
+ loop_scope="module",
293
+ loop_factory=AnotherCustomEventLoop
294
+ )
295
+ async def test_with_a_different_custom_loop_factory():
296
+ ...
235
297
"""
236
298
)
237
299
)
238
300
301
+ result = pytester .runpytest ("--asyncio-mode=strict" , "-s" , "--setup-show" )
302
+ result .assert_outcomes (errors = 2 )
303
+
304
+
305
+ def test_conflicting_loop_factories_in_tests_and_fixtures_raise_error (
306
+ pytester : Pytester ,
307
+ ):
308
+ pytester .makeini ("[pytest]\n asyncio_default_fixture_loop_scope = function" )
239
309
pytester .makepyfile (
240
310
dedent (
241
311
"""\
@@ -246,22 +316,109 @@ def test_asyncio_marker_event_loop_factories(pytester: Pytester):
246
316
class CustomEventLoop(asyncio.SelectorEventLoop):
247
317
pass
248
318
249
- @pytest.mark.asyncio(loop_factory=CustomEventLoop)
250
- async def test_has_different_event_loop():
251
- assert type(asyncio.get_running_loop()).__name__ == "CustomEventLoop"
319
+ class AnotherCustomEventLoop(asyncio.SelectorEventLoop):
320
+ pass
321
+
322
+ @pytest_asyncio.fixture(loop_scope="module", loop_factory=CustomEventLoop)
323
+ async def fixture_with_custom_loop_factory():
324
+ ...
325
+
326
+ @pytest.mark.asyncio(
327
+ loop_scope="module",
328
+ loop_factory=AnotherCustomEventLoop
329
+ )
330
+ async def test_trying_to_override_fixtures_loop_factory(
331
+ fixture_with_custom_loop_factory
332
+ ):
333
+ # Fails, because it tries to use a different loop factory on the
334
+ # same runner as the first test
335
+ ...
336
+ """
337
+ )
338
+ )
339
+
340
+ result = pytester .runpytest ("--asyncio-mode=strict" )
341
+ result .assert_outcomes (passed = 1 , errors = 1 )
252
342
253
- @pytest_asyncio.fixture(loop_factory=CustomEventLoop)
254
- async def custom_fixture():
255
- yield asyncio.get_running_loop()
256
343
257
- async def test_with_fixture(custom_fixture):
258
- # Both of these should be the same...
259
- type(asyncio.get_running_loop()).__name__ == "CustomEventLoop"
260
- type(custom_fixture).__name__ == "CustomEventLoop"
344
+ def test_conflicting_loop_factories_in_fixtures_raise_error (pytester : Pytester ):
345
+ pytester .makeini ("[pytest]\n asyncio_default_fixture_loop_scope = function" )
346
+ pytester .makepyfile (
347
+ dedent (
348
+ """\
349
+ import asyncio
350
+ import pytest_asyncio
351
+ import pytest
261
352
353
+ class CustomEventLoop(asyncio.SelectorEventLoop):
354
+ pass
355
+
356
+ class AnotherCustomEventLoop(asyncio.SelectorEventLoop):
357
+ pass
358
+
359
+ @pytest_asyncio.fixture(loop_scope="module", loop_factory=CustomEventLoop)
360
+ async def fixture_with_custom_loop_factory():
361
+ ...
362
+
363
+ @pytest_asyncio.fixture(
364
+ loop_scope="module",
365
+ loop_factory=AnotherCustomEventLoop
366
+ )
367
+ async def another_fixture_with_custom_loop_factory():
368
+ ...
369
+
370
+ @pytest.mark.asyncio(loop_scope="module")
371
+ async def test_requesting_two_fixtures_with_different_loop_facoties(
372
+ fixture_with_custom_loop_factory,
373
+ another_fixture_with_custom_loop_factory,
374
+ ):
375
+ ...
262
376
"""
263
377
)
264
378
)
265
379
266
- result = pytester .runpytest ("--asyncio-mode=auto" )
267
- result .assert_outcomes (passed = 2 )
380
+ result = pytester .runpytest ("--asyncio-mode=strict" , "-s" , "--setup-show" )
381
+ result .assert_outcomes (errors = 1 )
382
+
383
+
384
+ def test_conflicting_loop_factories_in_transitive_fixtures_raise_error (
385
+ pytester : Pytester ,
386
+ ):
387
+ pytester .makeini ("[pytest]\n asyncio_default_fixture_loop_scope = function" )
388
+ pytester .makepyfile (
389
+ dedent (
390
+ """\
391
+ import asyncio
392
+ import pytest_asyncio
393
+ import pytest
394
+
395
+ class CustomEventLoop(asyncio.SelectorEventLoop):
396
+ pass
397
+
398
+ class AnotherCustomEventLoop(asyncio.SelectorEventLoop):
399
+ pass
400
+
401
+ @pytest_asyncio.fixture(loop_scope="module", loop_factory=CustomEventLoop)
402
+ async def fixture_with_custom_loop_factory():
403
+ ...
404
+
405
+ @pytest_asyncio.fixture(
406
+ loop_scope="module",
407
+ loop_factory=AnotherCustomEventLoop
408
+ )
409
+ async def another_fixture_with_custom_loop_factory(
410
+ fixture_with_custom_loop_factory
411
+ ):
412
+ ...
413
+
414
+ @pytest.mark.asyncio(loop_scope="module")
415
+ async def test_requesting_two_fixtures_with_different_loop_facories(
416
+ another_fixture_with_custom_loop_factory,
417
+ ):
418
+ ...
419
+ """
420
+ )
421
+ )
422
+
423
+ result = pytester .runpytest ("--asyncio-mode=strict" )
424
+ result .assert_outcomes (errors = 1 )
0 commit comments