Testing Strategies

Testing strategies I use across projects:

Testing Pyramid

    /\
   /  \    E2E Tests (10%)
  /____\   - User workflows
 /      \  - Critical paths
/________\  
          Integration Tests (20%)
          - API endpoints
          - Database interactions
          
          Unit Tests (70%)
          - Pure functions
          - Business logic

Unit Testing Best Practices

// AAA Pattern: Arrange, Act, Assert
describe('UserService', () => {
  it('should create user with valid data', async () => {
    // Arrange
    const userData = { name: 'John', email: 'john@test.com' };
    const mockRepo = { save: jest.fn().mockResolvedValue(userData) };
    const userService = new UserService(mockRepo);
    
    // Act
    const result = await userService.createUser(userData);
    
    // Assert
    expect(result).toEqual(userData);
    expect(mockRepo.save).toHaveBeenCalledWith(userData);
  });
});

Integration Testing

// Test API endpoints with real database
describe('POST /api/users', () => {
  beforeEach(async () => {
    await cleanDatabase();
  });
  
  it('should create user and return 201', async () => {
    const response = await request(app)
      .post('/api/users')
      .send({ name: 'John', email: 'john@test.com' })
      .expect(201);
      
    expect(response.body.data.name).toBe('John');
  });
});

E2E Testing with Cypress

describe('User Registration', () => {
  it('should register new user', () => {
    cy.visit('/register');
    cy.get('[data-testid="name"]').type('John Doe');
    cy.get('[data-testid="email"]').type('john@test.com');
    cy.get('[data-testid="password"]').type('password123');
    cy.get('[data-testid="submit"]').click();
    cy.url().should('include', '/dashboard');
  });
});

Test Data Management

  • Use factories for test data
  • Clean database between tests
  • Mock external services
  • Use test-specific configurations