@@ -400,6 +400,35 @@ The ``smtp_connection`` connection will be closed after the test finished
400
400
execution because the ``smtp_connection `` object automatically closes when
401
401
the ``with `` statement ends.
402
402
403
+ Using the contextlib.ExitStack context manager finalizers will always be called
404
+ regardless if the fixture *setup * code raises an exception. This is handy to properly
405
+ close all resources created by a fixture even if one of them fails to be created/acquired:
406
+
407
+ .. code-block :: python
408
+
409
+ # content of test_yield3.py
410
+
411
+ import contextlib
412
+
413
+ import pytest
414
+
415
+ from .utils import connect
416
+
417
+
418
+ @pytest.fixture
419
+ def equipments ():
420
+ with contextlib.ExitStack():
421
+ r = []
422
+ for port in (' C1' , ' C3' , ' C28' ):
423
+ equip = connect(port)
424
+ stack.callback(equip.disconnect)
425
+ r.append(equip)
426
+ yield r
427
+
428
+ In the example above, if ``"C28" `` fails with an exception, ``"C1" `` and ``"C3" `` will still
429
+ be properly closed. Of course, if an exception happens before the finalize function is
430
+ registered then it will not be executed.
431
+
403
432
Note that if an exception happens during the *setup * code (before the ``yield `` keyword), the
404
433
*teardown * code (after the ``yield ``) will not be called.
405
434
@@ -428,29 +457,32 @@ Here's the ``smtp_connection`` fixture changed to use ``addfinalizer`` for clean
428
457
return smtp_connection # provide the fixture value
429
458
430
459
431
- Both ``yield `` and ``addfinalizer `` methods work similarly by calling their code after the test
432
- ends, but ``addfinalizer `` has two key differences over ``yield ``:
460
+ Here's the ``equipments `` fixture changed to use ``addfinalizer `` for cleanup:
433
461
434
- 1. It is possible to register multiple finalizer functions.
462
+ .. code-block :: python
435
463
436
- 2. Finalizers will always be called regardless if the fixture *setup * code raises an exception.
437
- This is handy to properly close all resources created by a fixture even if one of them
438
- fails to be created/acquired::
464
+ # content of test_yield3.py
439
465
440
- @pytest.fixture
441
- def equipments(request):
442
- r = []
443
- for port in ('C1', 'C3', 'C28'):
444
- equip = connect(port)
445
- request.addfinalizer(equip.disconnect)
446
- r.append(equip)
447
- return r
448
-
449
- In the example above, if ``"C28" `` fails with an exception, ``"C1" `` and ``"C3" `` will still
450
- be properly closed. Of course, if an exception happens before the finalize function is
451
- registered then it will not be executed.
466
+ import contextlib
467
+
468
+ import pytest
469
+
470
+ from .utils import connect
452
471
453
472
473
+ @pytest.fixture
474
+ def equipments (request ):
475
+ r = []
476
+ for port in (' C1' , ' C3' , ' C28' ):
477
+ equip = connect(port)
478
+ request.addfinalizer(equip.disconnect)
479
+ r.append(equip)
480
+ return r
481
+
482
+
483
+ Both ``yield `` and ``addfinalizer `` methods work similarly by calling their code after the test
484
+ ends.
485
+
454
486
.. _`request-context` :
455
487
456
488
Fixtures can introspect the requesting test context
0 commit comments