Testing Overview
Testing Overview
Global Watch employs a comprehensive testing strategy that combines multiple testing approaches to ensure code quality, reliability, and maintainability. Our testing philosophy emphasizes high confidence with minimal manual intervention.
Testing Philosophy
Our testing approach follows these core principles:
- Test-Driven Development (TDD) - Write tests first, then implement
- Dual Testing Approach - Combine unit tests and property-based tests
- Automation First - Minimize manual testing through comprehensive automation
- High Coverage - Maintain minimum 70% coverage across the codebase
Testing Stack
Global Watch uses industry-standard testing tools:
| Tool | Purpose | Location |
|---|---|---|
| Vitest | Unit and integration tests | apps/web/**/*.test.ts |
| fast-check | Property-based testing | apps/web/**/*.test.ts |
| Playwright | End-to-end testing | apps/e2e/tests/ |
Test Types
Unit Tests
Unit tests verify individual functions, classes, and modules work correctly in isolation:
- Test specific examples and edge cases
- Fast execution (milliseconds)
- High coverage of business logic
- Co-located with source files using
.test.tssuffix
Learn more about Unit Testing →
Property-Based Tests
Property-based tests verify universal properties hold across all valid inputs:
- Generate random test cases automatically
- Find edge cases humans might miss
- Validate invariants and contracts
- Minimum 100 iterations per property
Learn more about Property-Based Testing →
End-to-End Tests
E2E tests verify complete user flows work correctly:
- Test real browser interactions
- Validate multi-step workflows
- Cross-browser compatibility
- Integration with real services
Learn more about E2E Testing →
Coverage Requirements
Global Watch maintains strict coverage requirements:
| Category | Minimum Coverage |
|---|---|
| Overall | 70% |
| Core components | 90% |
| Business logic | 80% |
| Domain entities | 90% |
| Server actions | 80% |
Running Tests
Quick Commands
# Run all unit tests
pnpm --filter web test:run
# Run tests in watch mode
pnpm --filter web test
# Run with coverage report
pnpm --filter web test:coverage
# Run E2E tests
pnpm --filter e2e test
# Run specific test file
pnpm --filter web test:run path/to/file.test.tsTest Scripts
The following scripts are available in the monorepo:
# Unit and integration tests
pnpm --filter web test # Watch mode
pnpm --filter web test:run # Single run
pnpm --filter web test:ui # Vitest UI
pnpm --filter web test:coverage # With coverage
# E2E tests
pnpm --filter e2e test # Run all E2E tests
pnpm --filter e2e test --headed # With visible browser
pnpm --filter e2e test --ui # Playwright UI mode
pnpm --filter e2e test --debug # Debug modeTest Organization
File Structure
Tests are organized alongside source files:
apps/web/
├── app/
│ └── feature/
│ ├── _lib/
│ │ ├── server/
│ │ │ ├── server-actions.ts
│ │ │ └── __tests__/
│ │ │ └── server-actions.test.ts
│ │ └── schemas/
│ └── _components/
│ ├── my-component.tsx
│ └── __tests__/
│ └── my-component.test.tsx
├── core/
│ └── domain/
│ └── project/
│ ├── project.entity.ts
│ └── __tests__/
│ └── project.entity.test.ts
└── lib/
└── utils/
├── helpers.ts
└── __tests__/
└── helpers.test.tsE2E Test Structure
E2E tests are organized by feature:
apps/e2e/
├── tests/
│ ├── authentication/
│ │ ├── auth.po.ts # Page Object
│ │ └── auth.spec.ts # Test specs
│ ├── projects/
│ │ ├── projects.po.ts
│ │ └── projects.spec.ts
│ └── team-accounts/
│ ├── team-accounts.po.ts
│ └── team-accounts.spec.ts
└── playwright.config.tsTesting Best Practices
1. Test Behavior, Not Implementation
// ✅ CORRECT - Test behavior
it('should calculate project area from geometry', () => {
const project = Project.create({ geometry: mockPolygon });
expect(project.calculateArea()).toBeCloseTo(100.5);
});
// ❌ WRONG - Test implementation details
it('should call _calculatePolygonArea method', () => {
const project = Project.create({ geometry: mockPolygon });
expect(project._calculatePolygonArea).toHaveBeenCalled();
});2. Use Descriptive Test Names
// ✅ CORRECT - Descriptive names
describe('Project.archive()', () => {
it('should set status to archived when project is active', () => {});
it('should throw error when project is already archived', () => {});
it('should update the updatedAt timestamp', () => {});
});
// ❌ WRONG - Vague names
describe('Project', () => {
it('should work', () => {});
it('test archive', () => {});
});3. Avoid Mocking When Possible
// ✅ CORRECT - Test real behavior
it('should validate email format', () => {
const result = Email.create('invalid-email');
expect(result.ok).toBe(false);
});
// ❌ AVOID - Excessive mocking
it('should validate email', () => {
const mockValidator = jest.fn().mockReturnValue(false);
// This doesn't test real validation
});4. Test Edge Cases
describe('Hectares.create()', () => {
it('should accept zero', () => {
const result = Hectares.create(0);
expect(result.ok).toBe(true);
});
it('should reject negative values', () => {
const result = Hectares.create(-1);
expect(result.ok).toBe(false);
});
it('should handle very large values', () => {
const result = Hectares.create(Number.MAX_SAFE_INTEGER);
expect(result.ok).toBe(true);
});
});CI/CD Integration
Tests run automatically in the CI/CD pipeline:
- Pre-commit - Lint and type checking
- Pull Request - Full test suite
- Merge to main - Full test suite + E2E
- Deploy - Smoke tests in staging
GitHub Actions Example
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
- uses: actions/setup-node@v4
- run: pnpm install
- run: pnpm typecheck
- run: pnpm --filter web test:run
- run: pnpm --filter e2e testDebugging Failed Tests
Unit Tests
# Run with verbose output
pnpm --filter web test:run --reporter=verbose
# Run specific test
pnpm --filter web test:run --grep "should calculate area"
# Use Vitest UI for debugging
pnpm --filter web test:uiE2E Tests
# Run with visible browser
pnpm --filter e2e test --headed
# Debug mode (step through)
pnpm --filter e2e test --debug
# View test traces
pnpm --filter e2e test --trace onNext Steps
- Unit Testing Guide - Vitest configuration and patterns
- Property-Based Testing - Using fast-check effectively
- E2E Testing Guide - Playwright setup and patterns