Skip to main content

Codi Testing Patterns

Codi Testing Patterns

When to Use This Skill

Use this skill when implementing codi testing patterns patterns in your codebase.

How to Use This Skill

  1. Review the patterns and examples below
  2. Apply the relevant patterns to your implementation
  3. Follow the best practices outlined in this skill

Level 1: Quick Reference (Under 500 tokens)

Test Organization

// Feature-based test structure
describe('UserAuthentication', () => {
describe('login', () => {
it('should authenticate valid credentials', async () => {
const result = await login('user@test.com', 'password');
expect(result.success).toBe(true);
});

it('should reject invalid credentials', async () => {
await expect(login('user@test.com', 'wrong'))
.rejects.toThrow('Invalid credentials');
});
});
});

Coverage Thresholds

// vitest.config.ts
export default {
coverage: {
provider: 'v8',
thresholds: {
lines: 80,
branches: 75,
functions: 80,
statements: 80,
},
},
};

Level 2: Implementation Details (Under 2000 tokens)

Test Factory Pattern

interface UserFactory {
create(overrides?: Partial<User>): User;
createMany(count: number): User[];
}

const userFactory: UserFactory = {
create(overrides = {}) {
return {
id: crypto.randomUUID(),
email: `user-${Date.now()}@test.com`,
name: 'Test User',
createdAt: new Date(),
...overrides,
};
},
createMany(count) {
return Array.from({ length: count }, () => this.create());
},
};

// Usage
const user = userFactory.create({ name: 'Custom Name' });
const users = userFactory.createMany(10);

Mock Patterns

// Service mock with spies
const mockUserService = {
getUser: vi.fn(),
updateUser: vi.fn(),
deleteUser: vi.fn(),
};

beforeEach(() => {
mockUserService.getUser.mockResolvedValue(userFactory.create());
mockUserService.updateUser.mockResolvedValue({ success: true });
});

afterEach(() => {
vi.clearAllMocks();
});

Integration Test Helpers

async function setupTestDatabase() {
const db = await createTestDatabase();
await runMigrations(db);
return {
db,
cleanup: () => db.destroy(),
};
}

describe('UserRepository', () => {
let db: Database;
let cleanup: () => Promise<void>;

beforeAll(async () => {
({ db, cleanup } = await setupTestDatabase());
});

afterAll(() => cleanup());

it('should create user', async () => {
const repo = new UserRepository(db);
const user = await repo.create(userFactory.create());
expect(user.id).toBeDefined();
});
});

Level 3: Complete Reference (Full tokens)

E2E Test Infrastructure

// Playwright page object
class LoginPage {
constructor(private page: Page) {}

async goto() {
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="submit"]');
}

async expectError(message: string) {
await expect(this.page.locator('.error')).toHaveText(message);
}

async expectRedirectTo(path: string) {
await this.page.waitForURL(`**${path}`);
}
}

test('user can login', async ({ page }) => {
const loginPage = new LoginPage(page);
await loginPage.goto();
await loginPage.login('user@test.com', 'password');
await loginPage.expectRedirectTo('/dashboard');
});

Best Practices:

  • Use factories for test data
  • Isolate tests with proper setup/teardown
  • Implement page objects for E2E
  • Set meaningful coverage thresholds
  • Run tests in CI on every commit

Success Output

When successful, this skill MUST output:

✅ SKILL COMPLETE: codi-testing-patterns

Completed:
- [x] Test organization patterns applied
- [x] Coverage thresholds configured
- [x] Test factories implemented
- [x] Integration test helpers created
- [x] E2E page objects established

Outputs:
- Test files with proper describe/it structure
- vitest.config.ts with coverage thresholds
- Test factories for domain models
- Integration test setup/teardown helpers
- E2E page object classes

Completion Checklist

Before marking this skill as complete, verify:

  • Tests organized by feature with clear describe blocks
  • Coverage thresholds set (80% lines, 75% branches)
  • Test factory pattern implemented for test data
  • Mock patterns established with proper cleanup
  • Integration tests have database setup/teardown
  • E2E tests use page object pattern
  • All tests pass in CI environment
  • Test outputs are deterministic and isolated

Failure Indicators

This skill has FAILED if:

  • ❌ Tests are not isolated (shared state between tests)
  • ❌ Coverage thresholds not configured or below 70%
  • ❌ Tests use hardcoded data instead of factories
  • ❌ Mock cleanup missing (tests pollute each other)
  • ❌ E2E tests use brittle selectors (no data-testid)
  • ❌ Integration tests don't clean up database
  • ❌ Tests fail intermittently in CI
  • ❌ Test files lack clear organization structure

When NOT to Use

Do NOT use this skill when:

  • Only need to run existing tests (use testing-specialist agent instead)
  • Writing simple unit tests for pure functions (use basic test patterns)
  • Need test execution/reporting only (use /test command)
  • Implementing specific framework tests (use framework-specific skills like vitest-patterns or playwright-patterns)
  • Need security/penetration testing (use security-testing-patterns skill)
  • Performance/load testing required (use performance-testing-patterns skill)

Use alternative skills:

  • vitest-patterns - Vitest-specific configuration and features
  • playwright-patterns - Playwright-specific E2E patterns
  • testing-specialist - General test execution and debugging
  • tdd-workflow - Test-driven development workflow

Anti-Patterns (Avoid)

Anti-PatternProblemSolution
Shared test stateTests fail when run in different orderUse beforeEach/afterEach for isolation
No test factoriesBrittle tests with hardcoded dataImplement factory pattern for test data
Missing mock cleanupMocks leak between testsUse afterEach(() => vi.clearAllMocks())
Direct DOM selectionE2E tests break on UI changesUse data-testid attributes with page objects
No database cleanupIntegration tests pollute databaseImplement proper teardown in afterAll
Testing implementationTests break on refactoringTest behavior, not implementation details
Low coverage thresholdsPoor test quality acceptanceSet minimum 80% coverage thresholds
Skipped tests in CIFalse confidence in test suiteNever skip tests; fix or remove them

Principles

This skill embodies these CODITECT principles:

  • #1 Separation of Concerns - Test organization mirrors feature structure
  • #3 Keep It Simple - Use factories and helpers to simplify test code
  • #5 Eliminate Ambiguity - Clear test names and assertion messages
  • #6 Clear, Understandable, Explainable - Tests serve as living documentation
  • #8 No Assumptions - Explicit setup/teardown, no shared state
  • #9 Search Before Create - Reuse test factories and helpers across test suites

Full Principles: CODITECT-STANDARD-AUTOMATION.md