Testing ensures that Python programs work correctly and reliably.
Benefits of testing:
- Finds bugs early
- Improves code quality
- Makes maintenance easier
- Prevents unexpected errors
Types of Testing
| Type | Purpose |
|---|---|
| Unit Testing | Test individual functions/modules |
| Integration Testing | Test combined components |
| Functional Testing | Test application behavior |
| System Testing | Test entire application |
Unit Testing
Unit testing checks small units of code such as:
- Functions
- Methods
- Classes
Python provides:
unittest
module for unit testing.
Example Function
def add(a, b):
return a + b
Writing Unit Test
import unittest
def add(a, b):
return a + b
class TestMath(unittest.TestCase):
def test_add(self):
self.assertEqual(add(2, 3), 5)
if __name__ == "__main__":
unittest.main()
Running Tests
Save file as:
test_math.py
Run:
python test_math.py
Common Assertion Methods
| Method | Purpose |
|---|---|
assertEqual(a, b) | Check equality |
assertNotEqual(a, b) | Check inequality |
assertTrue(x) | Check true |
assertFalse(x) | Check false |
assertIsNone(x) | Check None |
assertIn(a, b) | Check membership |
Example: Multiple Tests
import unittest
class TestString(unittest.TestCase):
def test_upper(self):
self.assertEqual(
"python".upper(),
"PYTHON"
)
def test_isdigit(self):
self.assertFalse("abc".isdigit())
if __name__ == "__main__":
unittest.main()
Setup and Teardown Methods
Used for preparing and cleaning test environment.
Example
import unittest
class TestExample(unittest.TestCase):
def setUp(self):
print("Setup executed")
def tearDown(self):
print("Teardown executed")
def test_sample(self):
self.assertEqual(1 + 1, 2)
if __name__ == "__main__":
unittest.main()
pytest
pytest is a powerful third-party testing framework.
Advantages:
- Simpler syntax
- Better output
- Easy fixtures
Install pytest
pip install pytest
Simple pytest Example
def add(a, b):
return a + b
def test_add():
assert add(2, 3) == 5
Run pytest
pytest
Multiple pytest Tests
def multiply(a, b):
return a * b
def test_multiply():
assert multiply(2, 4) == 8
def test_negative():
assert multiply(-1, 5) == -5
pytest Fixtures
Fixtures provide reusable test setup.
import pytest
@pytest.fixture
def sample_data():
return [1, 2, 3]
def test_length(sample_data):
assert len(sample_data) == 3
Mocking in Python
Mocking replaces real objects with fake objects during testing.
Useful when testing:
- APIs
- Databases
- External services
Python provides:
unittest.mock
Example Function
import requests
def get_data():
response = requests.get(
"https://api.example.com"
)
return response.status_code
Mocking API Request
from unittest.mock import patch
import unittest
class TestAPI(unittest.TestCase):
@patch("requests.get")
def test_get_data(self, mock_get):
mock_get.return_value.status_code = 200
import requests
response = requests.get(
"https://api.example.com"
)
self.assertEqual(
response.status_code,
200
)
if __name__ == "__main__":
unittest.main()
Mock Object Example
from unittest.mock import Mock
database = Mock()
database.get_user.return_value = {
"name": "Aditya"
}
print(database.get_user())
Debugging Techniques
Debugging helps identify and fix errors.
Using print()
Simplest debugging method.
x = 10
print("Value of x:", x)
Using pdb Debugger
Python provides built-in debugger:
pdb
Example
import pdb
x = 10
y = 0
pdb.set_trace()
print(x / y)
Common pdb Commands
| Command | Purpose |
|---|---|
n | Next line |
c | Continue |
q | Quit |
p variable | Print variable |
Exception Traceback
Python displays traceback for errors.
def divide(a, b):
return a / b
print(divide(10, 0))
Output:
ZeroDivisionError
Logging for Debugging
Use logging instead of many print statements.
Example
import logging
logging.basicConfig(level=logging.INFO)
logging.info("Program started")
logging.warning("Warning message")
logging.error("Error occurred")
Debugging with VS Code
VS Code provides:
- Breakpoints
- Variable inspection
- Step execution
Steps:
- Open Python file
- Click beside line number
- Press
F5 - Start debugging
Test Coverage
Coverage measures how much code is tested.
Install coverage:
pip install coverage
Run coverage:
coverage run test_math.py
coverage report
Practical Example
Calculator Testing
import unittest
def divide(a, b):
return a / b
class TestCalculator(unittest.TestCase):
def test_divide(self):
self.assertEqual(
divide(10, 2),
5
)
def test_zero_division(self):
with self.assertRaises(
ZeroDivisionError
):
divide(10, 0)
if __name__ == "__main__":
unittest.main()
Best Practices
✅ Write small test cases
✅ Test edge cases
✅ Use mocking for external services
✅ Use logging for debugging
✅ Automate tests regularly
Summary
In this chapter you learned:
✅ Unit testing
✅ unittest module
✅ pytest basics
✅ Mocking
✅ Debugging techniques






