No description
- Python 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| __pycache__ | ||
| calculator.py | ||
| main.py | ||
| README.md | ||
| test_calculator.py | ||
Unit Testing in Python - Training Project
Overview
This project demonstrates fundamental unit testing concepts for junior software engineers. It contains a simple calculator function with comprehensive unit tests to illustrate best practices in test-driven development.
Project Structure
unit-testing-project/
├── README.md
├── main.py # Entry point - controls execution
├── calculator.py # Contains the add function with error handling
└── test_calculator.py # Comprehensive unit tests
What You'll Learn
- Writing testable functions with proper error handling
- Creating comprehensive unit tests using Python's unittest framework
- Testing both happy paths and edge cases
- Validating error handling in your code
- Running and interpreting test results
Prerequisites
- Python 3.6 or higher
- No external dependencies required (uses Python's built-in unittest module)
Setup Instructions
1. Create Project Directory
mkdir unit-testing-project
cd unit-testing-project
2. Create the Files
Create three Python files and copy the code from each section below:
calculator.pytest_calculator.pymain.py
3. Verify Setup
Ensure all three files are in the same directory.
Running the Project
Run the Main Application
python main.py
This executes the calculator function with sample inputs.
Run the Unit Tests
python -m unittest test_calculator.py
Run Tests with Verbose Output
python -m unittest test_calculator.py -v
Run a Specific Test
python -m unittest test_calculator.TestCalculator.test_add_positive_numbers
Understanding the Code
calculator.py
Contains the add() function that:
- Accepts two numeric parameters
- Validates input types
- Returns the sum
- Raises appropriate exceptions for invalid inputs
test_calculator.py
Contains the test suite that validates:
- Happy paths: Normal, expected use cases
- Edge cases: Boundary conditions (zero, negatives, floats)
- Error conditions: Invalid inputs and type errors
- Special values: Very large numbers, infinity, NaN
main.py
Demonstrates practical usage of the calculator function with various test cases.
Test Coverage Breakdown
The test suite includes:
- Basic functionality tests - positive integers, negative numbers, zero
- Type validation tests - strings, None, lists, mixed types
- Float handling tests - decimal numbers, precision
- Edge case tests - very large numbers, infinity, NaN
- Error message validation - ensures clear error messages
Expected Test Results
When you run the tests, you should see output like:
..........
----------------------------------------------------------------------
Ran 10 tests in 0.001s
OK
Each dot represents a passed test. If a test fails, you'll see an 'F' instead.
Common Testing Patterns Demonstrated
- Arrange-Act-Assert: Each test sets up data, executes the function, and verifies results
- Testing exceptions: Using
assertRaises()to verify error handling - Descriptive test names: Clear names that describe what's being tested
- Test isolation: Each test is independent and can run in any order
Extending the Project
Try these exercises:
- Add a
subtract()function and write tests for it - Add a
multiply()function that handles zero properly - Write a test that deliberately fails to see what failure looks like
- Add test coverage for division with zero-division error handling
Key Takeaways
- Unit tests validate individual functions in isolation
- Good error handling makes functions more robust
- Tests should cover happy paths, edge cases, and error conditions
- Clear test names serve as documentation
- Running tests frequently catches bugs early
Additional Resources
Questions to Consider
- Why is it important to test error conditions, not just successful operations?
- How do unit tests help when refactoring code?
- What happens if you modify the
add()function but forget to update tests? - How would you test a function that depends on external services?