what is the order of setup/teardown in python unit tests?

  • Last Update :
  • Techknowledgy :

I have a discrepancy in understand of the basic unittest methods in python. Given this test file below:

import unittest, sys

class TestStringMethods(unittest.TestCase):

   def setUp(self):
   self.mystring = "example string"

def tearDown(self):
   del self.mystring

def test_upper(self):
   self.assertEqual('foo'.upper(), 'FOO')

def test_isupper(self):
   self.assertTrue('FOO'.isupper())
self.assertFalse('Foo'.isupper())

def test_split(self):
   s = 'hello world'
self.assertEqual(s.split(), ['hello', 'world'])
with self.assertRaises(TypeError):
   s.split(2)

My understanding based on what I've read ("Methods named setUp in a TestCase are run, automatically, before every test method.", http://gettingstartedwithdjango.com/en/lessons/testing-microblog/#toc1, etc) I interpret the order of events like:

1. set up self.mystring
2. run test_upper
3. tear down self.mystring

4. set up self.mystring
5. run test_isupper
6. tear down self.mystring

7. set up self.mystring
8. run test_split
9. tear down self.mystring

My co-workers interpret the docs as saying unittest works as follows:

1. set up self.mystring
2. run test_upper
3. run test_isupper
4. run test_split
5. tear down self.mystring

Suggestion : 2

The setUp() and tearDown() methods allow you to define instructions that will be executed before and after each test method. They are covered in more detail in the section Organizing test code.,Such a working environment for the testing code is called a test fixture. A new TestCase instance is created as a unique test fixture used to execute each individual test method. Thus setUp(), tearDown(), and __init__() will be called once per test.,If the setUp() method raises an exception while the test is running, the framework will consider the test to have suffered an error, and the test method will not be executed.,When called without arguments this function removes the control-c handler if it has been installed. This function can also be used as a test decorator to temporarily remove the handler while the test is being executed:

import unittest

class TestStringMethods(unittest.TestCase):

   def test_upper(self):
   self.assertEqual('foo'.upper(), 'FOO')

def test_isupper(self):
   self.assertTrue('FOO'.isupper())
self.assertFalse('Foo'.isupper())

def test_split(self):
   s = 'hello world'
self.assertEqual(s.split(), ['hello', 'world'])
# check that s.split fails when the separator is not a string
with self.assertRaises(TypeError):
   s.split(2)

if __name__ == '__main__':
   unittest.main()
...
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
Ran 3 tests in 0.000 s

OK
test_isupper(__main__.TestStringMethods)...ok
test_split(__main__.TestStringMethods)...ok
test_upper(__main__.TestStringMethods)...ok

   -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
Ran 3 tests in 0.001 s

OK
python - m unittest test_module1 test_module2
python - m unittest test_module.TestClass
python - m unittest test_module.TestClass.test_method
python - m unittest tests / test_something.py
python - m unittest - v test_module

Suggestion : 3

Test Setup and Teardown within a unittest.TestCase , Test Setup and Teardown within a unittest.TestCase ,Another benefit of registering cleanups this way is that it allows the programmer to put the cleanup code next to the setup code and it protects you in the event that a subclasser forgets to call super in tearDown.,Sometimes we want to prepare a context for each test to be run under. The setUp method is run prior to each test in the class. tearDown is run at the end of every test. These methods are optional. Remember that TestCases are often used in cooperative multiple inheritance so you should be careful to always call super in these methods so that base class's setUp and tearDown methods also get called. The base implementation of TestCase provides empty setUp and tearDown methods so that they can be called without raising exceptions:

Sometimes we want to prepare a context for each test to be run under. The setUp method is run prior to each test in the class. tearDown is run at the end of every test. These methods are optional. Remember that TestCases are often used in cooperative multiple inheritance so you should be careful to always call super in these methods so that base class's setUp and tearDown methods also get called. The base implementation of TestCase provides empty setUp and tearDown methods so that they can be called without raising exceptions:

import unittest

class SomeTest(unittest.TestCase):
   def setUp(self):
   super(SomeTest, self).setUp()
self.mock_data = [1, 2, 3, 4, 5]

def test(self):
   self.assertEqual(len(self.mock_data), 5)

def tearDown(self):
   super(SomeTest, self).tearDown()
self.mock_data = []

if __name__ == '__main__':
   unittest.main()

Note that in python2.7+, there is also the addCleanup method that registers functions to be called after the test is run. In contrast to tearDown which only gets called if setUp succeeds, functions registered via addCleanup will be called even in the event of an unhandled exception in setUp. As a concrete example, this method can frequently be seen removing various mocks that were registered while the test was running:

import unittest
import some_module

class SomeOtherTest(unittest.TestCase):
   def setUp(self):
   super(SomeOtherTest, self).setUp()

# Replace `some_module.method`
with a `mock.Mock`
my_patch = mock.patch.object(some_module, 'method')
my_patch.start()

# When the test finishes running, put the original method back.
self.addCleanup(my_patch.stop)

Suggestion : 4

The unittest module provides a rich set of tools for constructing and running tests. This section demonstrates that a small subset of the tools suffice to meet the needs of most users.,Test case instances are grouped together according to the features they test. unittest provides a mechanism for this: the test suite, represented by unittest‘s TestSuite class:,A testcase is created by subclassing unittest.TestCase. The three individual tests are defined with methods whose names start with the letters test. This naming convention informs the test runner about which methods represent tests.,Return a suite of all tests cases contained in the given module. This method searches module for classes derived from TestCase and creates an instance of the class for each test method defined for the class.

import random
import unittest

class TestSequenceFunctions(unittest.TestCase):

   def setUp(self):
   self.seq = range(10)

def test_shuffle(self):
   # make sure the shuffled sequence does not lose any elements
random.shuffle(self.seq)
self.seq.sort()
self.assertEqual(self.seq, range(10))

# should raise an exception
for an immutable sequence
self.assertRaises(TypeError, random.shuffle, (1, 2, 3))

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)

if __name__ == '__main__':
   unittest.main()
...
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
Ran 3 tests in 0.000 s

OK
suite = unittest.TestLoader().loadTestsFromTestCase(TestSequenceFunctions)
unittest.TextTestRunner(verbosity = 2).run(suite)
test_choice(__main__.TestSequenceFunctions)...ok
test_sample(__main__.TestSequenceFunctions)...ok
test_shuffle(__main__.TestSequenceFunctions)...ok

   -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
Ran 3 tests in 0.110 s

OK
python - m unittest test_module1 test_module2
python - m unittest test_module.TestClass
python - m unittest test_module.TestClass.test_method
python - m unittest - v test_module

Suggestion : 5

This section describes a classic and popular way how you can implement fixtures (setup and teardown test state) on a per-module/class/function basis.,If you have multiple test functions and test classes in a single module you can optionally implement the following fixture methods which will usually be called once for all the functions:,If you would rather define test functions directly at module level you can also use the following functions to implement fixtures:,teardown functions are not called if the corresponding setup function existed and failed/was skipped.

def setup_module(module):
   ""
" setup any state specific to the execution of the given module."
""

def teardown_module(module):
   ""
" teardown any state that was previously setup with a setup_module
method.
""
"
@classmethod
def setup_class(cls):
   ""
" setup any state specific to the execution of the given class (which
usually contains tests).
""
"

@classmethod
def teardown_class(cls):
   ""
" teardown any state that was previously setup with a call to
setup_class.
""
"
def setup_method(self, method):
   ""
" setup any state tied to the execution of the given method in a
class.setup_method is invoked
for every test method of a class.
""
"

def teardown_method(self, method):
   ""
" teardown any state that was previously setup with a setup_method
call.
""
"
def setup_function(function):
   ""
" setup any state tied to the execution of the given function.
Invoked
for every test
function in the module.
""
"

def teardown_function(function):
   ""
" teardown any state that was previously setup with a setup_function
call.
""
"