Test Design Patterns
Common Test Design Patterns
1. Arrange-Act-Assert (AAA) Pattern
def test_user_registration(self):
## Arrange: Setup test data and conditions
user_data = {
'username': 'testuser',
'email': '[email protected]'
}
## Act: Perform the action being tested
user = UserRegistration.register(user_data)
## Assert: Verify the expected outcomes
self.assertIsNotNone(user)
self.assertEqual(user.username, 'testuser')
Test Design Strategies
Test Coverage Levels
graph TD
A[Unit Testing] --> B[Integration Testing]
B --> C[System Testing]
C --> D[Acceptance Testing]
Pattern Comparison
Pattern |
Use Case |
Complexity |
Recommended For |
AAA |
Simple, clear tests |
Low |
Most unit tests |
Given-When-Then |
Behavior-driven tests |
Medium |
Complex scenarios |
Mock Object |
External dependency testing |
High |
API, Database tests |
Advanced Testing Patterns
Mocking Dependencies
from unittest.mock import Mock, patch
class TestPaymentSystem:
def test_payment_processing(self):
## Create a mock payment gateway
mock_gateway = Mock()
mock_gateway.process_payment.return_value = True
## Use patch to replace real dependency
with patch('payment_module.PaymentGateway', return_value=mock_gateway):
result = process_payment(100)
self.assertTrue(result)
Parameterized Testing
@pytest.mark.parametrize('input,expected', [
(2, 4),
(3, 9),
(4, 16)
])
def test_square_function(input, expected):
assert square(input) == expected
Test Design Principles
- Keep tests independent
- Test one behavior per test
- Use meaningful test names
- Minimize test logic
Error Handling in Tests
def test_error_scenarios():
with self.assertRaises(ValueError):
process_invalid_input(None)
with self.assertRaises(TypeError):
process_invalid_input([])
At LabEx, we emphasize creating robust test designs that ensure comprehensive software quality and reliability.