Python unittest
Python unittest is used to write unit test cases for testing our code programmatically. Properly written test cases help us to test if the project/application requirements are met.
In this tutorial, we will learn how to use unittest library to write test cases for a Calculator application.
unittest Example
Let us create a Calculator program calc.py
, which contains two methods: add()
and subtract()
as shown in the following.
calc.py
def add(a, b):
return a + b
def subtract(a, b):
return a - b
Now, we shall write a class test_calc.py
that inherits unittest.TestCase
, contains two tests, one for each of the method in calc.py
.
test_calc.py
import unittest
import calc
class TestCalc(unittest.TestCase):
def test_add(self):
self.assertEqual(calc.add(4, 8), 12)
def test_subtract(self):
self.assertEqual(calc.subtract(8, 2), 6)
if __name__ == '__main__':
unittest.main()
Output
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
Test Case Class (TestCalc) Breakdown
Let us understand test_calc.py in the above example statement by statement.
1. Import unittest
import unittest
unittest is a builtin library. To use TestCase class, we must import unittest.
2. Import your code
import calc
Since we are writing test cases in a separate Python File, import your code that you would like to test. For this example, both calc.py
, and test_calc.py
are in the same location.
3. Subclass TestCase
class TestCalc(unittest.TestCase):
The class we are writing to test must inherit TestCase class of unittest library, so that, we can access the assert methods and many more functionalities, which we shall see in the following tutorials in detail.
4. Write Unit Test
def test_add(self):
self.assertEqual(calc.add(4, 8), 12)
The method name for a unit test must start with the word test
.
Inside the method, we may call an assert method. In this example, we called assertEqual()
method which asserts if the arguments are equal in value. assertEqual()
method is present in unittest.TestCase
class, which we inherited for our class TestCalc
.
In this method we are testing add()
method of calc.py
. add(4, 8)
must return 12 as per our requirement. Therefore, we are asserting that the value returned by add(4, 8)
and 12 must be equal, using assertEqual() method.
Similarly, the following method is used to test calc.subtract()
method.
def test_subtract(self):
self.assertEqual(calc.subtract(8, 2), 6)
5. Run Tests
if __name__ == '__main__':
unittest.main()
The above code starts running the test cases.
6. Output
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
The two dots in the first line represent the number of test cases run.
The description Ran 2 tests in 0.000s
describes the number of test run and the time taken to run these tests.
The text OK
represents that all the test cases are passed.
Multiple Assertions in a TestCase
In our previous example, we had methods test_add()
and test_subtract()
which had only one assert statement in each. But, we can have as many assert statements as required for testing the respective method/requirement.
For example, let us say, we would like to test all the edge cases for calc.add()
method, like: adding two positive numbers; two negative numbers; one positive and one negative number; one zero and one non-zero number. Similarly, we write these edge scenarios for testing subtract() method.
calc.py
remains the same as in the example above. We are only modifying our tests to be thorough.
test_calc.py
import unittest
import calc
class TestCalc(unittest.TestCase):
def test_add(self):
self.assertEqual(calc.add(4, 8), 12)
self.assertEqual(calc.add(4, -8), -4)
self.assertEqual(calc.add(-4, -8), -12)
self.assertEqual(calc.add(4, 0), 4)
def test_subtract(self):
self.assertEqual(calc.subtract(8, 2), 6)
self.assertEqual(calc.subtract(8, -2), 10)
self.assertEqual(calc.subtract(-8, -2), -6)
self.assertEqual(calc.subtract(8, 0), 8)
if __name__ == '__main__':
unittest.main()
Output
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
Failed TestCase
Now, let us modify test_add()
in such a way that one of the assertion statements fail. This is only to observe how the output would be when a test case fails.
test_calc.py
import unittest
import calc
class TestCalc(unittest.TestCase):
def test_add(self):
self.assertEqual(calc.add(4, 8), 5)
def test_subtract(self):
self.assertEqual(calc.subtract(8, 2), 6)
if __name__ == '__main__':
unittest.main()
Output
F.
======================================================================
FAIL: test_add (__main__.TestCalc)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/tutorialkart/Desktop/Projects/PythonTutorial/test_calc.py", line 7, in test_add
self.assertEqual(calc.add(4, 8), 5)
AssertionError: 12 != 5
----------------------------------------------------------------------
Ran 2 tests in 0.000s
FAILED (failures=1)
The output is self explanatory that there is one failure with AssertionError
at the statement self.assertEqual(calc.add(4, 8), 5)
.