This chapter covers how to ensure your code is reliable, robust, and maintainable by introducing Unit Testing and key Python Best Practices, including the essential PEP 8 style guide. Writing code correctly is only half the battle; writing code well is what makes a professional developer.
1. Introduction to Unit Testing
Testing is the process of verifying that your code behaves exactly as expected. Unit Testing focuses on testing the smallest parts of the application (units), usually individual functions or methods, in isolation.
A. The unittest Module
Python’s unittest module is the built-in framework for creating and running tests.
- Test Case: A class that inherits from
unittest.TestCase. Each method within this class starting withtest_is an individual test. - Assertions: Methods (like
assertEqual,assertTrue) used to check if the actual result matches the expected result.
B. Example Test Structure
If you have a function add(a, b) in a file called my_math.py:
# File: my_math.py
def add(a, b):
return a + b
You would write your tests in a separate file, often named test_my_math.py:
# File: test_my_math.py
import unittest
from my_math import add
# Create a test case class
class TestMyMathFunctions(unittest.TestCase):
# Test method must start with 'test_'
def test_add_integers(self):
# Assert that the function call equals the expected value
self.assertEqual(add(5, 7), 12)
def test_add_floats(self):
# Assert checks for floating point numbers
self.assertAlmostEqual(add(0.1, 0.2), 0.3)
# Run the tests when the script is executed directly
if __name__ == '__main__':
unittest.main()
- Running Tests: Execute the test file from your terminal:
python -m unittest test_my_math.py
2. Best Practices: Writing Pythonic Code
“Pythonic” refers to code that uses the features of the Python language effectively to be readable, concise, and efficient.
| Principle | Non-Pythonic Example | Pythonic Example |
| Iterate Directly | for i in range(len(my_list)): print(my_list[i]) | for item in my_list: print(item) |
| Conditional Assignment | if x > 10: status = 'High' else: status = 'Low' | status = 'High' if x > 10 else 'Low' (Ternary Operator) |
| List Creation | squares = []; for i in nums: squares.append(i**2) | squares = [i**2 for i in nums] (List Comprehension) |
| Safe Dictionary Access | if 'key' in my_dict: val = my_dict['key'] else: val = None | val = my_dict.get('key') (get() method) |
3. Code Style and Readability (PEP 8)
PEP 8 is the official style guide for writing Python code. Adhering to it ensures consistency, making code easier to read, debug, and maintain for everyone (including future you).
- Whitespace: Use 4 spaces for indentation. Never mix spaces and tabs.
- Line Length: Limit all lines to a maximum of 79 characters.
- Naming Conventions (Crucial):
- Functions, Variables, Modules: Use
snake_case(lowercase with underscores, e.g.,user_name,calculate_total). - Classes: Use
PascalCase(Capitalized words, e.g.,MyClass,VehicleModel). - Constants: Use
UPPER_CASE_SNAKE(e.g.,MAX_ATTEMPTS).
- Functions, Variables, Modules: Use
- Blank Lines: Use two blank lines to separate top-level definitions (functions and classes) and one blank line to separate method definitions inside a class.
Tool for Enforcement: Linters and Formatters
Use automated tools to check and fix PEP 8 compliance:
- Linters: Flake8 (checks style and basic errors).
- Formatters: Black (automatically reformats code to be PEP 8 compliant).
