Files
motovaultpro/docs/TESTING.md
Eric Gullickson d4156cf521 Stuff
2025-11-04 18:38:06 -06:00

7.5 KiB

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

# 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

# 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

{
  "validVehicle": {
    "vin": "1HGBH41JXMN109186",
    "nickname": "Test Honda",
    "color": "Blue"
  },
  "vpicResponse": {
    "Make": "Honda",
    "Model": "Civic", 
    "ModelYear": "2021"
  }
}

Testing Commands Reference

Development Testing

# 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

# 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

# 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

// 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

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

# 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

# Check container health
make logs-backend

# Restart with fresh state
make rebuild

Database Connection Issues

# Check postgres container
docker compose logs postgres

# Reset database
make clean && make start

Test Timeout Issues

# Increase timeout in jest config
# Or debug hanging connections
npm test -- --detectOpenHandles

Continuous Integration

Pre-commit Testing

All tests must pass before commits:

# 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 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

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