Lesson 28: Unit Testing in Python

๐ŸŽฏ Lesson Objective

To understand how to test Python code automatically using the unittest module, ensuring functions and classes behave as expected.


๐Ÿงฉ 1. What Is Unit Testing?

Unit Testing involves testing individual units (functions, methods, or classes) to verify correctness.

Benefits:

  • Catch bugs early
  • Ensure reliability
  • Facilitate safe refactoring

โš™๏ธ 2. Importing the unittest Module

import unittest

๐Ÿงฑ 3. Structure of a Unit Test

  1. Import unittest and the module to test
  2. Create a class inheriting from unittest.TestCase
  3. Define test methods starting with test_
  4. Use assertions to check results
  5. Run tests using unittest.main()

Example 1 โ€” Testing a Simple Function

Code to test (math_ops.py):

def add(a, b):
    return a + b

def multiply(a, b):
    return a * b

Unit Test (test_math_ops.py):

import unittest
from math_ops import add, multiply

class TestMathOps(unittest.TestCase):
    def test_add(self):
        self.assertEqual(add(2, 3), 5)
        self.assertEqual(add(-1, 1), 0)

    def test_multiply(self):
        self.assertEqual(multiply(2, 3), 6)
        self.assertNotEqual(multiply(2, 0), 1)

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

Output:

..
----------------------------------------------------------------------
Ran 2 tests in 0.001s

OK

๐Ÿ”น 4. Common Assertions

AssertionPurpose
assertEqual(a, b)Check a == b
assertNotEqual(a, b)Check a != b
assertTrue(x)Check x is True
assertFalse(x)Check x is False
assertIsNone(x)Check x is None
assertIsNotNone(x)Check x is not None
assertRaises(Exception, func, *args)Check function raises exception

Example 2 โ€” Testing Exceptions

def divide(a, b):
    return a / b

import unittest

class TestDivide(unittest.TestCase):
    def test_divide_by_zero(self):
        with self.assertRaises(ZeroDivisionError):
            divide(10, 0)

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

Output:

.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

Example 3 โ€” Testing Classes

Code to test (employee.py):

class Employee:
    def __init__(self, name, salary):
        self.name = name
        self.salary = salary

    def apply_raise(self, percent):
        self.salary += self.salary * percent

Unit Test (test_employee.py):

import unittest
from employee import Employee

class TestEmployee(unittest.TestCase):
    def setUp(self):
        self.emp = Employee("Alice", 50000)

    def test_apply_raise(self):
        self.emp.apply_raise(0.1)
        self.assertEqual(self.emp.salary, 55000)

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

๐Ÿ”น 5. Running Tests

  • Command line:
python -m unittest test_math_ops.py
  • Discover all tests automatically:
python -m unittest discover

๐Ÿ”น 6. Test Fixtures

  • setUp() โ†’ runs before each test
  • tearDown() โ†’ runs after each test
def setUp(self):
    self.file = open("data.txt", "w")

def tearDown(self):
    self.file.close()

๐Ÿ”น 7. Using Mock Objects

  • Use unittest.mock to replace real objects in tests.
from unittest.mock import patch
import requests

def get_status(url):
    response = requests.get(url)
    return response.status_code

import unittest

class TestAPI(unittest.TestCase):
    @patch('requests.get')
    def test_get_status(self, mock_get):
        mock_get.return_value.status_code = 200
        status = get_status("https://example.com")
        self.assertEqual(status, 200)

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *