Initial Commit
This commit is contained in:
305
docs/TESTING.md
Normal file
305
docs/TESTING.md
Normal file
@@ -0,0 +1,305 @@
|
||||
# Testing Guide
|
||||
|
||||
Comprehensive testing strategy for MotoVaultPro Modified Feature Capsule architecture.
|
||||
|
||||
## Testing Philosophy
|
||||
|
||||
Each feature capsule contains complete, isolated test suites with no cross-feature dependencies.
|
||||
|
||||
## Test Structure
|
||||
|
||||
### Per Feature Organization
|
||||
```
|
||||
backend/src/features/[name]/tests/
|
||||
├── fixtures/ # Test data
|
||||
├── unit/ # Isolated unit tests
|
||||
│ ├── [name].service.test.ts
|
||||
│ └── [external].client.test.ts
|
||||
└── integration/ # Full API tests
|
||||
└── [name].integration.test.ts
|
||||
```
|
||||
|
||||
## Docker Testing Workflow
|
||||
|
||||
### Primary Test Command
|
||||
```bash
|
||||
# Run all tests (backend + frontend) in containers
|
||||
make test
|
||||
```
|
||||
|
||||
This executes:
|
||||
- Backend: `docker compose exec backend npm test`
|
||||
- Frontend: runs Jest in a disposable Node container mounting `./frontend`
|
||||
|
||||
### Feature-Specific Testing
|
||||
```bash
|
||||
# Test single feature (complete isolation)
|
||||
make shell-backend
|
||||
npm test -- features/vehicles
|
||||
|
||||
# Test specific test type
|
||||
npm test -- features/vehicles/tests/unit
|
||||
npm test -- features/vehicles/tests/integration
|
||||
|
||||
# Test with coverage
|
||||
npm test -- features/vehicles --coverage
|
||||
|
||||
# Frontend only
|
||||
make test-frontend
|
||||
```
|
||||
|
||||
### Test Environment Setup
|
||||
1. **Container-Based**: All tests run inside Docker containers
|
||||
2. **Database**: Uses the development database in the stack (`motovaultpro`)
|
||||
3. **Mock External APIs**: No real API calls during testing (where implemented)
|
||||
4. **Cleanup**: Prefer transactions/cleanup per test; see feature tests for patterns
|
||||
|
||||
## Test Types
|
||||
|
||||
### Unit Tests
|
||||
**Location**: `features/[name]/tests/unit/`
|
||||
**Purpose**: Test business logic in isolation
|
||||
**Mocking**: All external dependencies mocked
|
||||
|
||||
Example: `vehicles.service.test.ts`
|
||||
- Tests VIN validation logic
|
||||
- Tests vehicle creation with mocked vPIC responses
|
||||
- Tests caching behavior with mocked Redis
|
||||
- Tests error handling paths
|
||||
|
||||
### Integration Tests
|
||||
**Location**: `features/[name]/tests/integration/`
|
||||
**Purpose**: Test complete API workflows
|
||||
**Database**: Real test database with transactions
|
||||
|
||||
Example: `vehicles.integration.test.ts`
|
||||
- Tests complete POST /api/vehicles workflow
|
||||
- Tests authentication middleware
|
||||
- Tests database persistence
|
||||
- Tests error responses
|
||||
|
||||
### Test Fixtures
|
||||
**Location**: `features/[name]/tests/fixtures/`
|
||||
**Purpose**: Reusable test data
|
||||
**Format**: JSON files with valid test objects
|
||||
|
||||
Example: `vehicles.fixtures.json`
|
||||
```json
|
||||
{
|
||||
"validVehicle": {
|
||||
"vin": "1HGBH41JXMN109186",
|
||||
"nickname": "Test Honda",
|
||||
"color": "Blue"
|
||||
},
|
||||
"vpicResponse": {
|
||||
"Make": "Honda",
|
||||
"Model": "Civic",
|
||||
"ModelYear": "2021"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Testing Commands Reference
|
||||
|
||||
### Development Testing
|
||||
```bash
|
||||
# Enter backend container
|
||||
make shell-backend
|
||||
|
||||
# Run all tests
|
||||
npm test
|
||||
|
||||
# Run specific feature
|
||||
npm test -- features/vehicles
|
||||
npm test -- features/fuel-logs
|
||||
npm test -- features/maintenance
|
||||
npm test -- features/stations
|
||||
|
||||
# Run with file watching
|
||||
npm run test:watch
|
||||
|
||||
# Run single test file
|
||||
npm test -- vehicles.service.test.ts
|
||||
|
||||
# Run tests matching pattern
|
||||
npm test -- --testNamePattern="VIN validation"
|
||||
|
||||
# Frontend tests (Jest)
|
||||
make test-frontend
|
||||
```
|
||||
|
||||
### Coverage Reports
|
||||
```bash
|
||||
# Generate coverage for specific feature
|
||||
npm test -- features/vehicles --coverage
|
||||
|
||||
# View coverage report
|
||||
open coverage/lcov-report/index.html
|
||||
```
|
||||
|
||||
### Container Management
|
||||
```bash
|
||||
# Restart containers with fresh database
|
||||
make rebuild
|
||||
|
||||
# View test logs
|
||||
make logs-backend
|
||||
|
||||
# Clean all test data
|
||||
make clean && make start
|
||||
```
|
||||
|
||||
## Test Configuration
|
||||
|
||||
### Jest Configuration
|
||||
- Backend: `backend/jest.config.js`
|
||||
- Frontend: `frontend/jest.config.cjs`
|
||||
- React + TypeScript via `ts-jest`
|
||||
- jsdom environment
|
||||
- Testing Library setup in `frontend/setupTests.ts`
|
||||
|
||||
### Database Testing
|
||||
- **DB**: Same as development (`motovaultpro`) within Docker
|
||||
- **Transactions**: Recommended pattern is one transaction per test
|
||||
- **Isolation**: Keep tests independent; avoid shared state
|
||||
- **Seeding**: Use feature-level fixtures when needed
|
||||
|
||||
### Coverage and Availability
|
||||
- Full test suite exists for `vehicles`.
|
||||
- Other features (e.g., `fuel-logs`, `stations`, `maintenance`) have placeholders and are being built out.
|
||||
|
||||
### Mock Strategy
|
||||
- **External APIs**: Completely mocked (vPIC, Google Maps)
|
||||
- **Database**: Real database with transactions
|
||||
- **Redis**: Mocked for unit tests, real for integration
|
||||
- **Auth**: Mocked JWT tokens for protected endpoints
|
||||
|
||||
## Test Data Management
|
||||
|
||||
### Fixtures Strategy
|
||||
```javascript
|
||||
// In test files
|
||||
import fixtures from '../fixtures/vehicles.fixtures.json';
|
||||
|
||||
describe('Vehicle Service', () => {
|
||||
it('should create vehicle', async () => {
|
||||
const result = await vehicleService.create(
|
||||
fixtures.validVehicle,
|
||||
'user123'
|
||||
);
|
||||
expect(result.make).toBe('Honda');
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### Database Seeding
|
||||
```javascript
|
||||
beforeEach(async () => {
|
||||
// Clean slate for each test
|
||||
await db.query('TRUNCATE TABLE vehicles CASCADE');
|
||||
|
||||
// Insert test-specific data
|
||||
await db.query('INSERT INTO vehicles ...', testData);
|
||||
});
|
||||
```
|
||||
|
||||
## Debugging Tests
|
||||
|
||||
### Debug Single Test
|
||||
```bash
|
||||
# Run specific test with debugging
|
||||
npm test -- --testNamePattern="should create vehicle" --verbose
|
||||
|
||||
# Debug integration test
|
||||
npm test -- features/vehicles/tests/integration --detectOpenHandles
|
||||
```
|
||||
|
||||
### Common Issues
|
||||
|
||||
#### Container Connection Issues
|
||||
```bash
|
||||
# Check container health
|
||||
make logs-backend
|
||||
|
||||
# Restart with fresh state
|
||||
make rebuild
|
||||
```
|
||||
|
||||
#### Database Connection Issues
|
||||
```bash
|
||||
# Check postgres container
|
||||
docker compose logs postgres
|
||||
|
||||
# Reset database
|
||||
make clean && make start
|
||||
```
|
||||
|
||||
#### Test Timeout Issues
|
||||
```bash
|
||||
# Increase timeout in jest config
|
||||
# Or debug hanging connections
|
||||
npm test -- --detectOpenHandles
|
||||
```
|
||||
|
||||
## Continuous Integration
|
||||
|
||||
### Pre-commit Testing
|
||||
All tests must pass before commits:
|
||||
```bash
|
||||
# Run linting and tests
|
||||
npm run lint
|
||||
npm test
|
||||
|
||||
# In Docker environment
|
||||
make test
|
||||
```
|
||||
|
||||
### Feature Development Workflow
|
||||
1. **Write tests first**: TDD approach preferred
|
||||
2. **Run tests continuously**: Use `npm run test:watch`
|
||||
3. **Test in containers**: Always verify with `make test`
|
||||
4. **Check coverage**: Ensure new code is covered
|
||||
5. **Integration last**: Run full test suite before PR
|
||||
|
||||
## Test Performance
|
||||
|
||||
### Parallel Execution
|
||||
- Jest runs tests in parallel by default
|
||||
- Feature isolation allows true parallel testing
|
||||
- No shared state between feature tests
|
||||
|
||||
### Test Speed Optimization
|
||||
- **Unit tests**: Fast (< 1 second per test)
|
||||
- **Integration tests**: Medium (< 5 seconds per test)
|
||||
- **Full suite**: Target < 30 seconds total
|
||||
|
||||
### Database Optimization
|
||||
- Use transactions for rollback (faster than truncate)
|
||||
- Minimal fixture data
|
||||
- Avoid complex joins in test setup
|
||||
|
||||
## Error Testing Strategy
|
||||
|
||||
### Expected Error Cases
|
||||
```javascript
|
||||
describe('Error Handling', () => {
|
||||
it('should handle invalid VIN', async () => {
|
||||
await expect(
|
||||
vehicleService.create({ vin: 'INVALID' }, 'user123')
|
||||
).rejects.toThrow('Invalid VIN format');
|
||||
});
|
||||
|
||||
it('should handle vPIC API failure', async () => {
|
||||
mockVpicClient.decode.mockRejectedValue(new Error('API down'));
|
||||
|
||||
const result = await vehicleService.create(validVehicle, 'user123');
|
||||
expect(result.make).toBeNull(); // Graceful degradation
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### External Service Failures
|
||||
- Mock API failures to test error handling
|
||||
- Test timeout scenarios
|
||||
- Test network connectivity issues
|
||||
- Verify graceful degradation paths
|
||||
Reference in New Issue
Block a user