Reputation: 9095
I have a custom contextmanager I use (not a fixture) for setup and cleanup of a test:
@contextmanager
def db_content(*args, **kwargs):
instance = db_insert( ... )
yield instance
db_delete(instance)
def test_my_test():
with db_content( ... ) as instance:
# ...
assert result
The problem is that when the assertion fails, the db_delete()
code - meaning the post yield statements, are not being executed.
I can see that if I use a fixture this does work.
@pytest.fixture
def db_instance():
instance = db_insert( ... )
yield instance
db_delete(instance)
def test_my_test(db_instance):
# ...
assert result
However, fixtures are very inflexible. I would like to pass different arguments to my context each test, while using fixtures would force me to define a different fixture for each case.
Upvotes: 1
Views: 764
Reputation: 9095
contextlib does not execute the post-yield statements if an exception was thrown. This is by design. To make it work you would have to write:
@contextmanager
def db_content(*args, **kwargs):
instance = db_insert( ... )
try:
yield instance
finally:
db_delete(instance)
In my opinion this is counter-intuitive as the try is not on the yield itself.
I took the implementation of contextmanager
and made a safe version one that works as I expected, however its an entire code duplication, if anyone has a better workaround I'd love to see it.
Upvotes: 2