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

Ned Batchelder ned at nedbatchelder.com
Mon Aug 21 12:02:17 EDT 2017


On 8/20/17 9:32 PM, Neil Girdhar 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.
>
> Why not add two methods to unittest.TestCase whose default
> implementations are given below:
>
> class TestCase:
>
>     @contextmanager
>     def method_context(self):
>         self.setUp()
>         try:
>             yield
>         finally:
>             self.tearDown()
>
>     @contextmanager
>     def class_context(self):
>         self.setUpClass()
>         try:
>             yield
>         finally:
>             self.tearDown()
>
>
> Then, if for example someone wants to use a context manager in setUp,
> they can do so:
>
> class SomeTest(TestCase):
>
>     @contextmanager
>     def method_context(self):
>         with np.errstate(all='raise'):
>             with super().method_context():
>                 yield
>
> Best,
>
> Neil
>
>
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/

I've achieved a similar effect with this:

    def setup_with_context_manager(testcase, cm):
        """Use a contextmanager to setUp a test case.

        If you have a context manager you like::

            with ctxmgr(a, b, c) as v:
                # do something with v

        and you want to have that effect for a test case, call this
    function from
        your setUp, and it will start the context manager for your test,
    and end it
        when the test is done::

            def setUp(self):
                self.v = setup_with_context_manager(self, ctxmgr(a, b, c))

            def test_foo(self):
                # do something with self.v

        """
        val = cm.__enter__()
        testcase.addCleanup(cm.__exit__, None, None, None)
        return val


I think the use is easier than yours, which needs too much super and
@contextmanager boilerplate.

--Ned.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20170821/2e591214/attachment.html>


More information about the Python-ideas mailing list