Category: python
Introduction to Unit Testing with unittest
Published on 14 Aug 2026
Explanation
Unit testing is the process of testing individual parts of a program, such as functions or methods, to verify that they work as expected. Python provides the built-in unittest framework for creating automated tests. A test case is created by extending unittest.TestCase, and individual test methods usually start with the word test. The unittest framework provides assertion methods to compare the actual result with the expected result. Unit testing helps identify bugs early, improves code quality, and makes it safer to modify existing applications.
Code:
import unittest
def add(a, b):
return a + b
class TestCalculator(unittest.TestCase):
def test_add(self):
result = add(10, 20)
self.assertEqual(result, 30)
if __name__ == '__main__':
unittest.main()
Explanation
A unittest test class can contain multiple test methods, allowing different scenarios of a function to be tested. Each method should normally begin with test so that unittest can automatically discover and execute it. Testing multiple inputs helps verify that a function behaves correctly for normal values, negative values, zero, and other important cases. Well-designed test cases should cover both expected and boundary conditions.
Code:
import unittest
def multiply(a, b):
return a * b
class TestCalculator(unittest.TestCase):
def test_positive_numbers(self):
self.assertEqual(multiply(5, 4), 20)
def test_negative_numbers(self):
self.assertEqual(multiply(-5, 4), -20)
def test_zero(self):
self.assertEqual(multiply(10, 0), 0)
def test_decimal_numbers(self):
self.assertEqual(multiply(2.5, 2), 5.0)
if __name__ == '__main__':
unittest.main()
Explanation
Assertions are used to verify whether the actual result matches the expected result. Python's unittest framework provides many assertion methods. assertEqual() checks whether two values are equal, assertNotEqual() checks that they are different, assertTrue() and assertFalse() check Boolean conditions, assertIsNone() checks for None, and assertIn() checks whether a value exists in a collection. Using appropriate assertions makes tests clear and meaningful.
Code:
import unittest
class TestAssertions(unittest.TestCase):
def test_equal(self):
self.assertEqual(10 + 20, 30)
def test_not_equal(self):
self.assertNotEqual(10, 20)
def test_true(self):
self.assertTrue(10 > 5)
def test_false(self):
self.assertFalse(10 < 5)
def test_none(self):
value = None
self.assertIsNone(value)
def test_in(self):
names = ['John', 'Alice', 'David']
self.assertIn('Alice', names)
if __name__ == '__main__':
unittest.main()
Explanation
Unit tests should also verify that functions correctly handle invalid input and raise the expected exceptions. The assertRaises() method is used to verify that a particular exception is raised. This is useful for testing validation logic, division by zero, invalid values, missing files, and other error conditions. Testing exceptions ensures that applications fail in a controlled and predictable way instead of producing unexpected behavior.
Code:
import unittest
def divide(a, b):
if b == 0:
raise ValueError('Denominator cannot be zero')
return a / b
class TestDivision(unittest.TestCase):
def test_division(self):
self.assertEqual(divide(10, 2), 5)
def test_zero_denominator(self):
with self.assertRaises(ValueError):
divide(10, 0)
if __name__ == '__main__':
unittest.main()
Explanation
The setUp() method runs before every test method and can be used to prepare common test data or resources. The tearDown() method runs after every test method and can be used to clean up resources. These methods are useful when multiple tests require the same setup. In real-world projects, unit tests are commonly organized in a separate tests directory and are executed automatically during development or CI/CD pipelines. Testing business logic separately from database and API code makes applications easier to maintain.
Code:
import unittest
class Employee:
def __init__(self, name, salary):
self.name = name
self.salary = salary
def annual_salary(self):
return self.salary * 12
class TestEmployee(unittest.TestCase):
def setUp(self):
self.employee = Employee('John', 50000)
def tearDown(self):
self.employee = None
def test_name(self):
self.assertEqual(self.employee.name, 'John')
def test_salary(self):
self.assertEqual(self.employee.salary, 50000)
def test_annual_salary(self):
self.assertEqual(self.employee.annual_salary(), 600000)
if __name__ == '__main__':
unittest.main()