Hackforge Academy

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()

πŸš€ Learn Spring Boot with real-world projects

πŸ’‘ Build REST APIs step by step

🧠 Improve backend development skills

🎯 Get career-ready practical training

Join Our Free WhatsApp Community

Direct access to niche-specific mentors and peers on WhatsApp.

🐍

Python Community

Discuss Django, FastAPI, AI integration, and automation scripts with 15k+ developers.

Join Python Community
βš›οΈ

React Community

Master Next.js, Framer Motion, and State Management. Share your latest UI components.

Join React Community
β˜•

Java Community

Deep dives into Spring Boot, Microservices architecture, and high-performance backend ops.

Join Java Community