86

My Python version is 2.6.

I would like to execute the test setUp method only once since I do things there which are needed for all tests.

My idea was to create a boolean variable which will be set to 'true' after the first execution and then disable more than one call to the setup method.

class mySelTest(unittest.TestCase):
    setup_done = False

    def setUp(self):
        print str(self.setup_done)
            
        if self.setup_done:
            return
        self.setup_done = True
        print str(self.setup_done)

The output:

False

True

--- Test 1 ---

False

True

--- Test 2 ---

why is this not working? Did I miss anything?

Veltzer Doron
  • 843
  • 1
  • 10
  • 28
Kesandal
  • 1,103
  • 3
  • 10
  • 14

8 Answers8

116

You can use setUpClass to define methods that only run once per testsuite.

CharlesB
  • 75,315
  • 26
  • 174
  • 199
Daniel Roseman
  • 541,889
  • 55
  • 754
  • 786
  • Thanks for your reply. Since I'm using Python 2.6.6 setUpClass is not available. – Kesandal Jan 13 '13 at 17:52
  • 2
    @JohnM.: You can download the unittest2 backport package and get all the new stuff on your older python-dist. – Macke Jan 14 '13 at 12:32
  • The question deals with Python 2, but since the answer is also valid for Python 3 I changed the URL since Python 2 is deprecated. – CharlesB Nov 07 '19 at 21:00
70

Daniel's answer is correct, but here is an example to avoid some common mistakes I found, such as not calling super() in setUpClass() when TestCase is a subclass of unittest.TestCase (like in django.test or falcon.testing).

The documentation for setUpClass() doesn't mention that you need to call super() in such cases. You will get an error if you don't, as seen in this related question.

class SomeTest(TestCase):
    def setUp(self):
        self.user1 = UserProfile.objects.create_user(resource=SomeTest.the_resource)

    @classmethod
    def setUpClass(cls):
        """ get_some_resource() is slow, to avoid calling it for each test use setUpClass()
            and store the result as class variable
        """
        super(SomeTest, cls).setUpClass()
        cls.the_resource = get_some_resource()
EliadL
  • 3,651
  • 2
  • 18
  • 34
Chemary
  • 1,141
  • 10
  • 17
3

setup_done is a class variable, not an instance variable.

You are referencing it as an instance variable:

self.setup_done

But you need to reference it as a class variable:

mySelTest.setup_done

Here's the corrected code:

class mySelTest(unittest.TestCase):
    setup_done = False

    def setUp(self):
        print str(mySelTest.setup_done)

        if mySelTest.setup_done:
            return
        mySelTest.setup_done = True
        print str(mySelTest.setup_done)
jersey bean
  • 2,248
  • 21
  • 26
3

If you ended up here because of need to load some data for testing... then as far as you are using Django 1.9+ please go for setUpTestData:

class MyTests(TestCase):

    @classmethod
    def setUpTestData(cls):
        # Set up data for the whole TestCase
        cls.foo = Foo.objects.create(bar="Test")

    def test1(self):
        self.assertEqual(self.foo.bar, 'Test') 
andilabs
  • 18,598
  • 13
  • 98
  • 133
2

Don't try to dedupe the calls to setUp, just call it once.

For example:

class MyClass(object):
    ...

def _set_up():
    code to do one-time setup

_set_up()

This will call _set_up() when the module's first loaded. I've defined it to be a module-level function, but you could equally make it a class method of MyClass.

Paul Hankin
  • 44,768
  • 11
  • 79
  • 97
2

Place all code you want set up once outside the mySelTest.

setup_done = False

class mySelTest(unittest.TestCase):

    def setUp(self):
        print str(setup_done)

        if setup_done:
            return

        setup_done = True
        print str(setup_done)

Another possibility is having a Singleton class that you instantiate in setUp(), which will only run the __new__ code once and return the object instance for the rest of the calls. See: Is there a simple, elegant way to define singletons?

class Singleton(object):
    _instance = None
    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super(Singleton, cls).__new__(
                            cls, *args, **kwargs)
            # PUT YOUR SETUP ONCE CODE HERE!
            cls.setUpBool = True

        return cls._instance

class mySelTest(unittest.TestCase):

    def setUp(self):
        # The first call initializes singleton, ever additional call returns the instantiated reference.
        print(Singleton().setUpBool)

Your way works too though.

Community
  • 1
  • 1
NuclearPeon
  • 4,789
  • 3
  • 40
  • 47
2

I'm using Python 3 and found that the cls reference is also available in the setup method and so the following works:

class TestThing(unittest.TestCase):

  @classmethod
  def setUpClass(cls):
    cls.thing = Thing() # the `thing` is only instantiated once

  def setup(self):
    self.thing = cls.thing # ...but set on each test case instance

  def test_the_thing(self):
    self.assertTrue(self.thing is not None)
Greg Ross
  • 3,321
  • 2
  • 22
  • 24
  • 1
    You cannot access cls within setUp, which is an instance method (the lower case setup() will not be called, because it is not a unittest setUp method, nor a method starting with 'test', which is probably why you did not get an error) However, once you define the class variables in setUpClass, you can simply call self.thing in all the instance methods – khuang834 Dec 10 '20 at 00:43
  • Thanks, @khuang834. You're right. This was an oversight on my part. – Greg Ross Dec 10 '20 at 20:52
0

for python >3 you can do it by defining startTestRun,stopTestRun of unittest.TestResult class. answer https://stackoverflow.com/a/64892396/2679740

ismail
  • 191
  • 1
  • 4