I have an existing context manager that is required by multiple tests. Instead of writing a with
block inside each test, I thought it would be better to make a fixture out of this context manager, and decorate the test with @pytest.mark.usefixtures("my_fixture")
.
I could reimplement the context manager as a fixture, but this seems like duplicating code. So I'd like to reference the original context manager in the new fixture.
This is what I have:
import my_context_manager
@pytest.fixture
def my_fixture(arg1, arg2):
with my_context_manager(arg1, arg2) as c:
yield c
Is this an appropriate way to convert an existing context manager into a fixture?
I should mention that I'm aware of contextlib.ContextDecorator
for writing a context manager that can be used as a decorator. But my context manager requires arguments, and these are not recognized when they are in a statement like @my_context_decorator(arg1, arg2)
.
Created a simple context manager, used it as the fixture and called that fixture in test.
Note: Advantage of using context manager this way is if the test fails still exit will execute. However, if you directly call context manager in test and if test failed post-yield statements will not execute.
createcontextmanager.py
class ContextManager():
def __init__(self):
print('init method called')
def __enter__(self):
print('enter method called')
return self
def __exit__(self, exc_type, exc_value, exc_traceback):
print('exit method called')
test_checkcontextmanagerwithfixture.py
import pytest
import createContextManager as ccm
@pytest.fixture(name ="c")
def check():
with ccm.ContextManager() as cm:
yield "hello"
@pytest.mark.stackoverflow
def test_checkficture(c):
assert c =="hello", 'failed'
Order of Output using 'python -m pytest -m stackoverflow -v -s' you might have something else. I think this is we want from the context manager.
- init method called
- enter method called
- PASSED
- exit method called