Pages

Monday, 25 April 2011

Calling only once setUp in unittest in python

In python unittest the setUp function gets called every time you need to run a single TestCase (no matter if you run it using TestSuite or simply unittest.main()).

So if you have to test something that requires a complex setUp routine (like loading 50000 records from SQL or preparing an orangemochafrappuccino) but that can be reused all along your TestSuite you have the same problem I had.

Now all around the internet there are posts saying "You could do that" or "One way to do that" or "Once I did that like this..." or even worse "The standard way of doing it is...".

But none of these posts really gets to the bottom of it, they all give you a piece of information. I couldn't find one place that told you "copy/paste this code and be happy".

So, after figuring it out, I can now tell you "copy/paste this code and be happy".
import unittest
from my_program import MyClass

class MyClassTest(unittest.TestCase):
    # First define a class variable that determines 
    # if setUp was ever run
    ClassIsSetup = False

    def setUp(self):
        # If it was not setup yet, do it
        if not self.ClassIsSetup:
            print "Initializing testing environment"
            # run the real setup
            self.setupClass()
            # remember that it was setup already
            self.__class__.ClassIsSetup = True
                               
    def setupClass(self):
        # Do the real setup
        unittest.TestCase.setUp(self)
        # you want to have persistent things to test
        self.__class__.myclass = MyClass()
        # (you can call this later with self.myclass)

You can do the same for the unittest.tearDown since it is exactly the same code.

11 comments:

  1. thanks Stefano,

    this code snipped is exactly what I needed ... and it works beautifully :)

    Rainer

    ReplyDelete
  2. Haha, worked for me too. I searched for this answer and, like yourself, found many partial and incomplete answers.

    ReplyDelete
  3. It just works, thanks!

    ReplyDelete
  4. @classmethod
    def setUpClass(cls):

    ReplyDelete
  5. Hello,

    I am getting error at import unittest, please let me know what i have to do....

    ReplyDelete
    Replies
    1. Read what the error says and try to fix it.

      Delete
  6. Thanks for sharing this snippet which is helpful to make setUp() to run once in a test class, however I tried to implement tearDown() in same way but when having multiple tests in test class, how to determine when to run tearDown() once only at end of all the tests in test class to set tearDown flag.

    ReplyDelete
  7. Tried it, but got the following error message:

    TypeError: unbound method setUpClass() must be called with Test instance as first argument (got nothing instead)

    My call to the method includes the keyword self however:

    def setUp(self):
    if not self.ClassIsSetup:
    self.setUpClass()
    self.__class__.ClassIsSetup = True

    ReplyDelete
  8. The snippet was written 4 yrs ago, IIRC on python2.8. Maybe something has changed in the way unittest works... if you get it working please also specify what version of python you are running.

    ReplyDelete
  9. Remove the setUp() method and rename setupClass to setUpClass(self). ALso use the decorator @classmethod

    Your code will look like this:

    [code language="python" highlight=6,7]
    import unittest
    from my_program import MyClass

    class MyClassTest(unittest.TestCase):

    @classmethod
    def setUpClass(self):
    # create an instance of object MyClass() so that
    # you can access it later in the code
    self.myclass = MyClass()
    # (you can call this later with self.myclass)
    [/code]

    ReplyDelete