[pytest-dev] Testing fixture teardown / finalisation

Bruno Oliveira nicoddemus at gmail.com
Wed Jan 6 13:26:08 EST 2021


Hi James,

What I suggest you do in your case is to decouple your code from the
fixture, so if you have something like this today:

    @pytest.fixture(scope="module")
    def my_work_reqs():
        # some
        # complicated
        # setup
        # code

        yield  x # some result

        # some
        # complicated
        # teardown
        # code

You can write instead:


    @contextmanager
    def handle_work_reqs():
        # some
        # complicated
        # setup
        # code
        try:
            yield x # some result
        finally:
            # some
            # complicated
            # teardown
            # code

    @pytest.fixture(scope="module")
    def my_work_reqs():
        with handle_work_reqs() as x:
            yield x

Now you can test handle_work_reqs normally, as it is not tied to the pytest
framework.

I like this approach in general, decoupling custom code from a framework is
a great way to make it easier to test.

HTH,
Bruno.

On Wed, Jan 6, 2021 at 2:37 PM James Cooke <me at jamescooke.info> wrote:

> Hi all,
>
> It's been a while since I've had to write a complicated and robust pytest
> fixture and I'm struggling with testing the teardown / finalisation code.
>
> Instead of boring you with the [my-work-project] requirements of cleaning
> up GCS after tests, I'll refer to the fixture in the docs
> https://docs.pytest.org/en/stable/fixture.html#fixture-finalization-executing-teardown-code
> :
>
>     @pytest.fixture(scope="module")
>     def smtp_connection():
>         smtp_connection = smtplib.SMTP("smtp.gmail.com", 587, timeout=5)
>         yield smtp_connection  # provide the fixture value
>         print("teardown smtp")
>         smtp_connection.close()
>
> My (very old) usual strategy for testing teardown of a fixture that uses
> `yield` would be:
>
> * Start test
>
>     - Instantiate the fixture.
>
>     - Manipulate the instance with `next()` to trigger the teardown.
>
>     - Ensure that teardown was successful - in this case assert that the
> SMTP connection returned when the fixture was instantiated was closed
> successfully.
>
> Given that since v4.1 (https://github.com/pytest-dev/pytest/issues/4545),
> the arrangement step of "Instantiate the fixture" does not work, could
> someone point me at the recommended method of testing fixture teardown?
>
> I would like to ensure that teardown is resilient and can resolve multiple
> conditions that can happen in [my-work-project]'s test suite. I can see
> that there are multiple tests on fixtures in
> https://github.com/pytest-dev/pytest/blob/48c9a96a03261e7cfa5aad0367a9186d9032904a/testing/python/fixtures.py
> , are there any preferred / recommended / efficient methods in this file?
> Alternatively, is there a way to by-pass the fixture wrapping that happens
> that prevents it being callable? Should I be using
> `smtp_connection.__pytest_wrapped__.obj()` to instantiate? (this seems bad)
>
> Any pointers / suggestions would be great.
>
> Thanks,
>
> James
>
>
> _______________________________________________
> pytest-dev mailing list
> pytest-dev at python.org
> https://mail.python.org/mailman/listinfo/pytest-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.python.org/pipermail/pytest-dev/attachments/20210106/961abb68/attachment.html>


More information about the pytest-dev mailing list