Files
motovaultpro/docs/TESTING.md
2025-12-21 11:31:10 -06:00

328 lines
8.1 KiB
Markdown

# 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
### Backend Testing
```bash
# Enter backend container shell
make shell-backend
# Inside container:
# Test all features
npm test
# Test single feature (complete isolation)
npm test -- --testPathPattern=src/features/vehicles
# Test specific test type
npm test -- --testPathPattern=src/features/vehicles/tests/unit
npm test -- --testPathPattern=src/features/vehicles/tests/integration
# Test with coverage
npm test -- --testPathPattern=src/features/vehicles --coverage
# Watch mode
npm run test:watch
```
### Frontend Testing
```bash
# From project root, run tests in frontend container
docker compose exec mvp-frontend npm test
# Watch mode
docker compose exec mvp-frontend npm run test:watch
# With coverage
docker compose exec mvp-frontend npm test -- --coverage
```
### 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 Data
**Location**: Inline within test files
**Purpose**: Test-specific mock data
**Format**: TypeScript objects defined in test files
Tests use inline mock data rather than external fixture files. Example pattern:
```typescript
const mockVehicle = {
vin: "1HGBH41JXMN109186",
nickname: "Test Honda",
color: "Blue"
};
const mockPlatformResponse = {
make: "Honda",
model: "Civic",
year: 2021
};
```
## Testing Commands Reference
### Development Testing
```bash
# Enter backend container
make shell-backend
# Run all tests
npm test
# Run specific feature
npm test -- --testPathPattern=src/features/vehicles
npm test -- --testPathPattern=src/features/fuel-logs
npm test -- --testPathPattern=src/features/maintenance
npm test -- --testPathPattern=src/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)
docker compose exec mvp-frontend npm test
```
### Coverage Reports
```bash
# Generate coverage for specific feature
npm test -- --testPathPattern=src/features/vehicles --coverage
# View coverage report
# Inside the container, open using your OS tooling,
# or copy the report out of the container as needed
```
### 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.ts`
- 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
All features have comprehensive test suites with unit and integration tests:
- `admin` - Unit + integration tests
- `documents` - Unit + integration tests
- `fuel-logs` - Unit + integration tests
- `maintenance` - Unit + integration tests
- `platform` - Unit + integration tests
- `stations` - Unit + integration tests (including community stations)
- `vehicles` - Unit + integration tests
### 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
### Inline Mock Data Strategy
```typescript
// In test files - define mock data inline
const mockVehicle = {
vin: '1HGBH41JXMN109186',
nickname: 'Test Honda',
year: 2021,
make: 'Honda',
model: 'Civic'
};
describe('Vehicle Service', () => {
it('should create vehicle', async () => {
const result = await vehicleService.create(mockVehicle, '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
# Backend: Enter shell and run tests
make shell-backend
npm run lint
npm test
# Frontend: Run tests from project root
docker compose exec mvp-frontend npm run lint
docker compose exec mvp-frontend npm 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 `docker compose exec mvp-backend npm 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