164

Is there a function that is fired at the beginning/end of a scenario of tests? The functions setUp and tearDown are fired before/after every single test.

I typically would like to have this:

class TestSequenceFunctions(unittest.TestCase):

    def setUpScenario(self):
        start() #launched at the beginning, once

    def test_choice(self):
        element = random.choice(self.seq)
        self.assertTrue(element in self.seq)

    def test_sample(self):
        with self.assertRaises(ValueError):
            random.sample(self.seq, 20)
        for element in random.sample(self.seq, 5):
            self.assertTrue(element in self.seq)

    def tearDownScenario(self):
        end() #launched at the end, once

For now, these setUp and tearDown are unit tests and spread in all my scenarios (containing many tests), one is the first test, the other is the last test.

Uyghur Lives Matter
  • 18,820
  • 42
  • 108
  • 144
swan
  • 1,863
  • 3
  • 14
  • 8
  • 7
    Which version? The unittest module has been expanded to include a module_setup and module_teardown in Python 2.7. – S.Lott Dec 05 '11 at 18:03
  • 4
    2.7 also introduced setUpClass() and tearDownClass() classmethods, which would let you have several classes in the same file with their own per-suite setup and teardown. – Per Fagrell Dec 05 '11 at 19:59
  • You can also [Disable logging for the entire module](https://stackoverflow.com/a/67608284/3684790) – Rafael Beirigo May 19 '21 at 17:45

5 Answers5

159

As of 2.7 (per the documentation) you get setUpClass and tearDownClass which execute before and after the tests in a given class are run, respectively. Alternatively, if you have a group of them in one file, you can use setUpModule and tearDownModule (documentation).

Otherwise your best bet is probably going to be to create your own derived TestSuite and override run(). All other calls would be handled by the parent, and run would call your setup and teardown code around a call up to the parent's run method.

David H. Clements
  • 3,590
  • 2
  • 24
  • 26
142

I have the same scenario, for me setUpClass and tearDownClass methods works perfectly

import unittest

class Test(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls._connection = createExpensiveConnectionObject()

    @classmethod
    def tearDownClass(cls):
        cls._connection.destroy()
Clare Macrae
  • 3,670
  • 2
  • 31
  • 45
CuriousLearner
  • 1,522
  • 1
  • 10
  • 7
  • 22
    This should be updated to be the accepted answer because it shows a correct example and these functions HAVE to be classmethods in order to work, which is not mentioned in the accepted answer. – NuclearPeon Nov 02 '18 at 00:26
21

Here is an example: 3 test methods access a shared resource, which is created once, not per test.

import unittest
import random

class TestSimulateLogistics(unittest.TestCase):

    shared_resource = None

    @classmethod
    def setUpClass(cls):
        cls.shared_resource = random.randint(1, 100)

    @classmethod
    def tearDownClass(cls):
        cls.shared_resource = None

    def test_1(self):
        print('test 1:', self.shared_resource)

    def test_2(self):
        print('test 2:', self.shared_resource)

    def test_3(self):
        print('test 3:', self.shared_resource)

kadir malak
  • 461
  • 4
  • 7
1

For python 2.5, and when working with pydev, it's a bit hard. It appears that pydev doesn't use the test suite, but finds all individual test cases and runs them all separately.

My solution for this was using a class variable like this:

class TestCase(unittest.TestCase):
    runCount = 0

    def setUpClass(self):
        pass # overridden in actual testcases

    def run(self, result=None):
        if type(self).runCount == 0:
            self.setUpClass()

        super(TestCase, self).run(result)
        type(self).runCount += 1

With this trick, when you inherit from this TestCase (instead of from the original unittest.TestCase), you'll also inherit the runCount of 0. Then in the run method, the runCount of the child testcase is checked and incremented. This leaves the runCount variable for this class at 0.

This means the setUpClass will only be ran once per class and not once per instance.

I don't have a tearDownClass method yet, but I guess something could be made with using that counter.

sanderd17
  • 420
  • 1
  • 4
  • 15
0
import unittest

class Test(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.shared_data = "dddd"

    @classmethod
    def tearDownClass(cls):
        cls.shared_data.destroy()

    def test_one(self):
        print("Test one")
    
    def test_two(self):
        print("Test 2")

For more visit Python unit test document

Chandan Sharma
  • 2,321
  • 22
  • 22