In this article you will learn what fixtures in unittest
are and how to use them. This will not teach you the basics of unittest
like creating test classes and running tests, for that check the following article:
We use fixtures
to create a standardized running environment for tests. They help to avoid repetition when there are actions that need to be taken before or after each test has been executed.
Basically, fixtures are functions or methods that are executed before and after a test has been executed. The are normally used to create setup and teardown functionalities. Setup fixtures are executed before the test is executed while teardown fixtures are executed after a test has been executed.
Fixtures are an important and very convenient feature of unittest
. With them, we can avoid repetitive actions and make our code shorter and concise.
Method-Level Fixtures
Method-level fixtures are executed before or after each method in a test class. Remember that tests in Python are implemented as a class that inherits from unittest.TestCase
, individual tests are implemented as methods of the class.
Unittest
provides two method-level fixtures:
setUp()
tearDown()
The setUp()
method is called before each test method is executed, while tearDown()
is called after each test method.
By convention the fixtures are placed before the tests.
import unittest
class TestExample(unittest.TestCase):
def setUp(self):
print()
print("Running setUp")
def tearDown(self):
print("Running tearDown")
def test_1(self):
print('Running Test 1')
self.assertEqual(5 + 5, 10)
def test_2(self):
print('Running Test 2')
self.assertEqual(2 * 8, 16)
if __name__ == '__main__':
unittest.main()
Running setUp
Running Test 1
Running tearDown
.
Running setUp
Running Test 2
Running tearDown
.
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
As you can see in the above example, the setUp()
method is being called before each of the test methods is executed and tearDown()
after.
In practical cases, we can use the setUp()
function to create test objects, open files and database, e.t.c. And in tearDown()
method, we can destroy the test objects, close the opened resources like files and databases, e.t.c
Class-level Fixtures
Class-level fixtures are executed before and after all test methods in the test class are run. Here we can initialize objects or perform operations that will be shared among all the test methods in the class.
There are two class-level fixtures:
setUpClass()
tearDownClass()
setUpClass()
is called before any test method is run. tearDownClass()
is called after all test methods are done.
Note that this are class methods, we therefore need to use the @classmethod decorator when defining them. The basic syntax is as shown below:
@classmethiod
def setUpClass(cls):
...
@classmethod
def tearDownClass(self):
...
Consider the following example:
import unittest
class TestExample(unittest.TestCase):
@classmethod
def setUpClass(self):
print("Running setUpClass")
print()
@classmethod
def tearDownClass(self):
print()
print("Running tearDownClass")
def test_1(self):
print('Running Test 1')
self.assertEqual(5 + 5, 10)
def test_2(self):
print('Running Test 2')
self.assertEqual(2 * 8, 16)
def test_3(self):
print('Running Test 3')
self.assertEqual(4 + 4, 8)
if __name__ == '__main__':
unittest.main()
Running setUpClass
Running Test 1.
Running Test 2.
Running Test 3.
Running tearDownClass
----------------------------------------------------------------------
Ran 3 tests in 0.000s
OK
Module-Level Fixtures
In some cases, you may have multiple test classes in a single file. Module-level fixtures can be used to create objects and perform operations that will be shared by all the test classes in the file/module.
There are two module level fixtures:
setUpModule()
tearDownModule()
setUpModule()
is called before all test classes are run while tearDownModule()
is called after tests in all classes have been run.
setUpModule()
and tearDownModule()
are not methods. They are standalone functions that are defined independent of any class.
import unittest
def setUpModule():
print('Running setUpModule')
print()
def tearDownModule():
print()
print('Running tearDownModule')
class TestExample1(unittest.TestCase):
def test_1(self):
print('Running Test 1')
self.assertEqual(5 + 5, 10)
def test_2(self):
print('Running Test 2')
self.assertEqual(2 * 8, 16)
class TestExample2(unittest.TestCase):
def test_a(self):
print('Running Test a')
self.assertEqual('a' + 'b', 'ab')
def test_b(self):
print('Running Test b')
self.assertEqual('a' * 3, 'aaa')
if __name__ == '__main__':
unittest.main()
Running setUpModule
Running Test 1.
Running Test 2.
Running Test a.
Running Test b.
Running tearDownModule
----------------------------------------------------------------------
Ran 4 tests in 0.001s
OK
A demo with all the fixtures
import unittest
def setUpModule():
print('Running setUpModule')
print()
def tearDownModule():
print()
print('Running tearDownModule')
class TestExample1(unittest.TestCase):
@classmethod
def setUpClass(cls):
print()
print("Running setUpClass for TestExample1")
@classmethod
def tearDownClass(cls):
print("Running tearDownClass for TestExample1")
print()
def setUp(self):
print()
print("Running setUp")
def tearDown(self):
print('running tearDown')
print()
def test_1(self):
print('Running Test 1')
self.assertEqual(5 + 5, 10)
def test_2(self):
print('Running Test 2')
self.assertEqual(2 * 8, 16)
class TestExample2(unittest.TestCase):
@classmethod
def setUpClass(cls):
print()
print("Running setUpClass for TestExample2")
@classmethod
def tearDownClass(cls):
print("Running tearDownClass for TestExample2")
print()
def setUp(self):
print()
print("Running setUp")
def tearDown(self):
print('running tearDown')
print()
def test_a(self):
print('Running Test a')
self.assertEqual('a' + 'b', 'ab')
def test_b(self):
print('Running Test b')
self.assertEqual('a' * 3, 'aaa')
if __name__ == '__main__':
unittest.main()
Running setUpModule
Running setUpClass for TestExample1
Running setUp
Running Test 1
running tearDown
Running setUp
Running Test 2
running tearDown
Running tearDownClass for TestExample1
Running setUpClass for TestExample2
Running setUp
Running Test a
running tearDown
Running setUp
Running Test b
running tearDown
Running tearDownClass for TestExample2
Running tearDownModule
----------------------------------------------------------------------
Ran 4 tests in 0.001s
OK
Conclusion
- Fixtures are used to perform some operations before or after a test is run.
- Setup fixtures are executed before the test is run, while teardown fixtures are executed after the test is run.
- Method-level fixtures are executed before and after each test method is run. These are
setUp()
andtearDown()
. They are implemented as instance methods. - Class-level fixtures are executed before and after all the test methods in a class are run. These are
setUpClass()
andtearDownClass()
. They are implemented as class methods using the@classmethod
decorator. - Module-level fixture are executed before and after the tests in all classes in the module are run. They are
setUpModule()
andtearDownModule()
. They are implemented as standalone functions.