320 lines
7.6 KiB
Markdown
320 lines
7.6 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 -- 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
|
|
|
|
# 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 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)
|
|
docker compose exec mvp-frontend npm test
|
|
```
|
|
|
|
### Coverage Reports
|
|
```bash
|
|
# Generate coverage for specific feature
|
|
npm test -- 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
|
|
- 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
|
|
# 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
|