## Testing Framework
### Phase 1: Test Strategy Design
```
I need a test automation strategy for:
**Application:** [Description]
**Tech Stack:** [Languages, frameworks]
**Current Coverage:** [% coverage, types of tests]
**Team Size:** [Number of developers]
Design a comprehensive test strategy:
1. **Testing Pyramid Distribution**
- Unit tests: [Target %] - Fast, isolated, high coverage
- Integration tests: [Target %] - Component interactions
- E2E tests: [Target %] - Critical user journeys
- Manual testing: [Scope] - Exploratory, UX validation
2. **Framework Selection**
- Unit testing: [Jest, pytest, JUnit, etc.]
- Integration: [Testcontainers, MSW, etc.]
- E2E: [Playwright, Cypress, Selenium]
- API testing: [Supertest, httpx, Postman]
3. **Coverage Goals**
- Line coverage target: [e.g., 80%]
- Branch coverage target: [e.g., 70%]
- Critical path coverage: [100% for core flows]
- Exclusions: [Generated code, config files]
4. **Test Organization**
- Directory structure
- Naming conventions
- Test data management
- Shared fixtures and utilities
5. **CI/CD Integration**
- When to run which tests
- Parallelization strategy
- Failure handling
- Reporting and notifications
```
### Phase 2: Unit Testing Patterns
```
Create unit tests for:
**Code Under Test:**
[Paste function or class]
**Testing Framework:** [Jest, pytest, etc.]
Apply these patterns:
1. **Arrange-Act-Assert (AAA)**
```
// Arrange: Set up test data and mocks
const user = createMockUser({ role: 'admin' });
// Act: Execute the code under test
const result = canAccessDashboard(user);
// Assert: Verify the outcome
expect(result).toBe(true);
```
2. **Test Naming Convention**
- `should_[expected behavior]_when_[condition]`
- `[method]_[scenario]_[expectedResult]`
3. **Edge Cases to Cover**
- Null/undefined inputs
- Empty arrays/strings
- Boundary values (0, -1, MAX_INT)
- Error conditions
- Async edge cases (timeouts, rejections)
4. **Mocking Strategy**
- What to mock: External services, databases, time
- What NOT to mock: Pure functions, value objects
- Mock vs. stub vs. spy usage
- Mock verification (called with correct args)
5. **Test Isolation**
- Each test independent
- No shared mutable state
- Deterministic (no random, no real time)
- Clean up after each test
Generate comprehensive test suite with edge cases.
```
### Phase 3: Integration Testing
```
Design integration tests for:
**Components to Test:** [Services, APIs, database layers]
**Integration Points:** [External APIs, databases, queues]
Integration testing approach:
1. **Database Integration**
```
// Using Testcontainers
beforeAll(async () => {
container = await new PostgreSQLContainer().start();
db = createConnection(container.getConnectionString());
await runMigrations(db);
});
afterEach(async () => {
await db.query('TRUNCATE users CASCADE');
});
test('should create user in database', async () => {
const user = await userService.create({ email: 'test@example.com' });
const saved = await db.query('SELECT \* FROM users WHERE id = $1', [user.id]);
expect(saved.rows[0].email).toBe('test@example.com');
});
```
2. **API Integration**
- Test real HTTP calls between services
- Verify request/response contracts
- Test error handling and timeouts
- Use API mocking for external services (MSW, WireMock)
3. **Message Queue Integration**
- Test publish/subscribe flows
- Verify message ordering
- Test dead letter handling
- Simulate consumer failures
4. **Cache Integration**
- Test cache hit/miss scenarios
- Verify cache invalidation
- Test TTL behavior
- Simulate cache unavailability
5. **Test Data Management**
- Factories for test data creation
- Database seeding strategies
- Cleanup between tests
- Snapshot testing for complex objects
Generate integration test setup and example tests.
```
### Phase 4: E2E Testing
````
Create E2E tests for:
**Application:** [Web app, mobile, API]
**Critical User Journeys:**
1. [Journey 1: e.g., User signup to first purchase]
2. [Journey 2: e.g., Search and filter products]
3. [Journey 3: e.g., Admin dashboard operations]
**Framework:** [Playwright, Cypress]
E2E testing strategy:
1. **Page Object Model**
```typescript
// pages/LoginPage.ts
export class LoginPage {
constructor(private page: Page) {}
async navigate() {
await this.page.goto('/login');
}
async login(email: string, password: string) {
await this.page.fill('[data-testid="email"]', email);
await this.page.fill('[data-testid="password"]', password);
await this.page.click('[data-testid="login-button"]');
}
async expectError(message: string) {
await expect(this.page.locator('.error')).toHaveText(message);
}
}
````
2. **Test Scenarios**
- Happy path: Complete user journey
- Error scenarios: Invalid inputs, network failures
- Edge cases: Empty states, long content
- Cross-browser: Chrome, Firefox, Safari
- Mobile viewports: Responsive behavior
3. **Test Data Setup**
- API calls to seed data before tests
- Database fixtures for known state
- Mock external services (payment, email)
- Deterministic test accounts
4. **Reliability Patterns**
- Auto-wait for elements (no explicit waits)
- Retry flaky network requests
- Isolated test accounts per run
- Screenshot/video on failure
5. **Performance Considerations**
- Parallelize test execution
- Share authentication state
- Minimize fixture setup time
- Use test sharding in CI
Generate E2E test suite with page objects.
```
## CI/CD Integration
```
Configure testing in CI/CD pipeline:
**CI Platform:** [GitHub Actions, GitLab CI, Jenkins]
**Test Types:** [Unit, integration, E2E]
Pipeline configuration:
1. **Test Stages**
```yaml
jobs:
unit-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm run test:unit -- --coverage
- uses: codecov/codecov-action@v3
integration-tests:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: test
steps:
- run: npm run test:integration
e2e-tests:
runs-on: ubuntu-latest
steps:
- run: npm run build
- run: npx playwright install
- run: npm run test:e2e
```
2. **When to Run**
- Unit tests: Every push
- Integration: Every PR
- E2E: Before merge to main
- Full suite: Nightly
3. **Failure Handling**
- Retry flaky tests (max 2 retries)
- Report results to PR comments
- Block merge on test failure
- Archive test artifacts (screenshots, logs)
4. **Parallelization**
- Split tests across runners
- Use test sharding
- Cache dependencies
- Run independent jobs concurrently
````
## Best Practices
1. **Test Independence**: Each test runs in isolation
2. **Determinism**: No random data, fixed timestamps
3. **Speed**: Unit tests < 10ms, integration < 1s
4. **Readability**: Tests are documentation
5. **Maintainability**: DRY fixtures, avoid brittle selectors
6. **Coverage Quality**: Cover edge cases, not just lines
7. **Continuous Refactoring**: Update tests as code evolves
8. **Flaky Test Management**: Fix or quarantine immediately
## Example Session
**User**: "How do I test a user registration flow with email verification?"
**Response**:
> Here's a comprehensive test strategy for user registration:
>
> **Unit Tests (Service Layer):**
> ```typescript
> describe('UserRegistrationService', () => {
> it('should create user with hashed password', async () => {
> const mockDb = createMockDb();
> const mockEmailService = createMockEmailService();
> const service = new UserRegistrationService(mockDb, mockEmailService);
>
> const result = await service.register({
> email: 'test@example.com',
> password: 'SecurePass123!'
> });
>
> expect(mockDb.users.create).toHaveBeenCalledWith(
> expect.objectContaining({
> email: 'test@example.com',
> passwordHash: expect.not.stringContaining('SecurePass123!')
> })
> );
> expect(mockEmailService.sendVerification).toHaveBeenCalled();
> });
> });
> ```
>
> **Integration Test (With Real Database):**
> ```typescript
> it('should persist user and send verification email', async () => {
> const { user, token } = await registrationService.register(testUser);
>
> const savedUser = await db.users.findById(user.id);
> expect(savedUser.emailVerified).toBe(false);
>
> const savedToken = await db.verificationTokens.findByUserId(user.id);
> expect(savedToken).toBeDefined();
> });
> ```
>
> **E2E Test (Full Flow):**
> ```typescript
> test('complete registration with email verification', async ({ page }) => {
> await page.goto('/register');
> await page.fill('[name="email"]', 'newuser@example.com');
> await page.fill('[name="password"]', 'SecurePass123!');
> await page.click('button[type="submit"]');
>
> await expect(page.locator('.success')).toContainText('Check your email');
>
> // Simulate email click via API
> const token = await getVerificationToken('newuser@example.com');
> await page.goto(`/verify?token=${token}`);
>
> await expect(page.locator('h1')).toContainText('Email Verified');
> });
> ```
## Related Resources
- [Testing Library](https://testing-library.com/)
- [Playwright Documentation](https://playwright.dev/)
- [Jest Best Practices](https://github.com/goldbergyoni/javascript-testing-best-practices)
- [Martin Fowler's Testing Guide](https://martinfowler.com/testing/)
````