[Python-ideas] Please consider adding context manager versions of setUp/tearDown to unittest.TestCase

Nick Coghlan ncoghlan at gmail.com
Tue Aug 22 08:42:02 EDT 2017


On 22 August 2017 at 15:34, Nick Coghlan <ncoghlan at gmail.com> wrote:
> On 21 August 2017 at 11:32, Neil Girdhar <mistersheik at gmail.com> wrote:
>> This question describes an example of the problem:
>> https://stackoverflow.com/questions/8416208/in-python-is-there-a-good-idiom-for-using-context-managers-in-setup-teardown.
>> You want to invoke a context manager in your setup/tearing-down, but the
>> easiest way to do that is to override run, which seems ugly.
>
> Using context managers when you can't use a with statement is one of
> the main use cases for contextlib.ExitStack():
>
>     def setUp(self):
>         self._resource_stack = stack = contextlib.ExitStack()
>         self._resource = stack.enter_context(MyResource())
>
>     def tearDown(self):
>         self._resource_stack.close()
>
> I posted that as an additional answer to the question:
> https://stackoverflow.com/questions/8416208/in-python-is-there-a-good-idiom-for-using-context-managers-in-setup-teardown/45809502#45809502

Sjoerd pointed out off-list that this doesn't cover the case where
you're acquiring multiple resources and one of the later acquisitions
fails, so I added the ExitStack idiom that covers that case (using
stack.pop_all() as the last operation in a with statement):

    def setUp(self):
        with contextlib.ExitStack() as stack:
            self._resource1 = stack.enter_context(GetResource())
            self._resource2 = stack.enter_context(GetOtherResource())
            # Failures before here -> immediate cleanup
            self.addCleanup(stack.pop_all().close)
            # Now cleanup won't happen until the cleanup functions run

I also remember that using addCleanup lets you avoid defining tearDown entirely.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia


More information about the Python-ideas mailing list