Question

I'm using unittest to test my terminal interactive utility. I have 2 test cases with very similar contexts: one tests for correct output and other for correct handling of user commands in interactive mode. Although, both cases mock sys.stdout to suppress actual output (output is performed in process of interactive work as well).

Consider the following:

class StdoutOutputTestCase(unittest.TestCase):
    """Tests whether the stuff is printed correctly."""

    def setUp(self):
        self.patcher_stdout = mock.patch('sys.stdout', StringIO())
        self.patcher_stdout.start()

    # Do testing

    def tearDown(self):
        self.patcher_stdout.stop()


class UserInteractionTestCase(unittest.TestCase):
    """Tests whether user input is handled correctly."""

    def setUp(self):
        self.patcher_stdout = mock.patch('sys.stdout', StringIO())
        self.patcher_stdout.start()

    # Do testing

    def tearDown(self):
        self.patcher_stdout.stop()      

What I don't like is that context setup is repeated here twice (for now; may be even more with time).

Is there a good way to set up common context for both cases? Can unittest.TestSuite help me? If yes, how? I couldn't find any example of common context setup.

I've also thought about defining a function setup_common_context, which would have been called from setUp of both cases, but it's still repetition.

Was it helpful?

Solution

I've solved this problem in my projects just by putting common setup code in a base class, and then putting test cases in derived classes. My derived class setUp and tearDown methods just call the super class implementations, and only do (de)initialization specific to those test cases. Also, keep in mind that you can put multiple tests in each test case, which might make sense if all the setup is the same.

class MyBaseTestCase(unittest.TestCase):
    def setUp(self):
        self.patcher_stdout = mock.patch('sys.stdout', StringIO())
        self.patcher_stdout.start()

    # Do **nothing**

    def tearDown(self):
        self.patcher_stdout.stop()

class StdoutOutputTestCase(MyBaseTestCase):
    """Tests whether the stuff is printed correctly."""

    def setUp(self):
        super(StdoutOutputTestCase, self).setUp()

        # StdoutOutputTestCase specific set up code

    # Do testing

    def tearDown(self):
        super(StdoutOutputTestCase, self).tearDown()

        # StdoutOutputTestCase specific tear down code

class UserInteractionTestCase(MyBaseTestCase):
     # Same pattern as StdoutOutputTestCase
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top