Reuse an existing context manager as a pytest fixture

Vermillion :

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).

pk786 :

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

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=3929&siteId=1