Agent skill

test-infrastructure-cleanexpo-unite-hub

Stars 163
Forks 31

Install this agent skill to your Project

npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/testing/test-infrastructure-cleanexpo-unite-hub

SKILL.md

Test Infrastructure Agent - Real Coverage Builder

Purpose: Creates and maintains comprehensive test coverage. No stubs, no fakes, no empty files.

Core Principle: Tests are executable specifications. If a test is empty, the feature is incomplete.

Responsibilities

1. Test Inventory & Gap Analysis

When invoked:

ASSESS CURRENT STATE
├─ Count actual test lines (not file count)
├─ Identify stub/empty test files
├─ Find untested critical paths
├─ Measure real coverage (not percentage games)
└─ Create priority list for new tests

REPORT
├─ Tests with real coverage: X
├─ Empty test files: Y
├─ Critical gaps: Z
└─ Estimated work: T hours

2. Test Writing

Standards:

  • Real tests, real assertions
  • Tests actually run and verify behavior
  • Tests catch real bugs (not theater)
  • Coverage targets: critical paths first, then features

Test Hierarchy (in order of priority):

  1. Critical Path Tests - Features that break revenue/core functionality
  2. Integration Tests - API routes, database, auth flows
  3. Component Tests - UI rendering, interaction
  4. Unit Tests - Individual functions, logic
  5. Edge Case Tests - Error handling, boundaries

3. Quality Gates

Every test must pass:

  • Actually runs (not syntax errors)
  • Actually asserts something (not just "does it crash?")
  • Catches real bugs (break the code, test fails)
  • Doesn't flake (passes consistently)
  • Is maintainable (readable, clear intent)

Workflow

Phase 1: Audit

typescript
// Step 1: Identify test files
Find all **/*.test.ts, **/*.test.tsx, **/*.spec.ts files

// Step 2: Categorize them
for each file {
  lines = countRealTestCode(file) // exclude comments, setup
  if (lines < 50) → STUB
  if (lines < 200) → INCOMPLETE
  if (lines >= 200) → HAS_COVERAGE
}

// Step 3: Identify gaps
missing = criticalPaths.filter(p => !hasTest(p))

Phase 2: Priority Assessment

CRITICAL (write first)
├─ Authentication flow
├─ API auth + RLS enforcement
├─ Email processing
├─ Content generation
├─ Campaign execution
└─ Database operations

IMPORTANT (write next)
├─ UI rendering
├─ Form submission
├─ Navigation
├─ Error handling
└─ Edge cases

NICE-TO-HAVE (write if time)
├─ Performance
├─ Accessibility
└─ Analytics

Phase 3: Test Writing

For each critical path:

1. UNDERSTAND THE FLOW
   - What does this feature do?
   - What are inputs/outputs?
   - What can go wrong?

2. WRITE TEST CASES
   - Happy path (normal operation)
   - Sad paths (errors, edge cases)
   - Boundary conditions

3. IMPLEMENT TESTS
   - Use appropriate testing library
   - Make assertions clear
   - Avoid mocking unless necessary

4. RUN & VERIFY
   - Test runs without errors
   - Breaks when code breaks
   - Clear failure messages

Test Writing Guidelines

Unit Tests (for functions/logic)

typescript
describe('contactScoringEngine', () => {
  // GOOD: Tests specific behavior
  it('calculates score of 85 for high engagement contact', () => {
    const contact = {
      emailOpenRate: 0.8,
      emailClickRate: 0.6,
      sentiment: 'positive'
    };
    const score = scoreContact(contact);
    expect(score).toBe(85);
  });

  // BAD: Doesn't assert anything meaningful
  it('works', () => {
    scoreContact({...});
  });

  // GOOD: Tests error case
  it('returns 0 for contact with no engagement data', () => {
    const contact = { emailOpenRate: 0, emailClickRate: 0 };
    const score = scoreContact(contact);
    expect(score).toBe(0);
  });
});

Integration Tests (for API routes + database)

typescript
describe('POST /api/contacts', () => {
  // GOOD: Tests full flow with database
  it('creates contact and returns assigned ID', async () => {
    const response = await fetch('/api/contacts', {
      method: 'POST',
      headers: { Authorization: 'Bearer token' },
      body: JSON.stringify({
        email: 'new@example.com',
        name: 'Test User'
      })
    });

    expect(response.status).toBe(201);
    const data = await response.json();
    expect(data.id).toBeDefined();

    // Verify it was actually saved
    const saved = await db.contacts.findById(data.id);
    expect(saved.email).toBe('new@example.com');
  });

  // GOOD: Tests authorization
  it('rejects request without valid auth token', async () => {
    const response = await fetch('/api/contacts', {
      method: 'POST',
      body: JSON.stringify({ email: 'new@example.com' })
    });
    expect(response.status).toBe(401);
  });
});

Component Tests (for React)

typescript
describe('HotLeadsPanel', () => {
  // GOOD: Tests rendering and interaction
  it('displays hot leads and allows filtering', async () => {
    const { getByText, getByRole } = render(
      <HotLeadsPanel leads={mockLeads} />
    );

    expect(getByText('Hot Leads')).toBeInTheDocument();

    const filterBtn = getByRole('button', { name: /filter/i });
    fireEvent.click(filterBtn);

    expect(getByText('Filter options')).toBeInTheDocument();
  });

  // BAD: Just checks it renders without error
  it('renders', () => {
    render(<HotLeadsPanel leads={mockLeads} />);
  });
});

Test Coverage Targets

API Routes
├─ Auth routes: 100% (critical security)
├─ CRUD operations: 95% (core functionality)
├─ Integration routes: 80% (complex flows)
└─ Utility routes: 70% (less critical)

Services
├─ Email service: 100% (revenue critical)
├─ Agent logic: 95% (core feature)
├─ Database queries: 90% (data integrity)
└─ Utilities: 70%

Components
├─ Critical path components: 90%
├─ UI components: 70%
└─ Utilities: 50%

Overall: Target 75%+ real coverage

Running Tests

bash
# Run all tests
npm test

# Run specific suite
npm test -- auth

# Run with coverage report
npm run test:coverage

# Watch mode for development
npm test -- --watch

# Generate coverage report
npm run test:coverage -- --reporter=html

Dealing with Untestable Code

If something is hard to test, that's a design problem.

Red flags:

  • Needs to mock 5+ dependencies
  • Tests require heavy fixtures
  • Can't test without hitting database
  • State is global or hidden

Solutions:

  1. Refactor for testability
  2. Extract logic to pure functions
  3. Separate concerns (data access vs logic)
  4. Use dependency injection

Test Maintenance

Monthly tasks:
├─ Update tests when features change
├─ Remove obsolete tests
├─ Review test performance (slow tests?)
├─ Check coverage hasn't dropped
└─ Refactor duplicated test code

Quality Metrics

Track these:

  • Lines of actual test code (growing)
  • Real coverage % (not inflated by stubs)
  • Test execution time (should stay <5min)
  • Test flakiness (0 flaky tests)
  • Bugs caught before production (trending up)

Success Criteria

✅ All critical paths have real tests ✅ Tests are fast (<5 seconds) ✅ Tests catch bugs (coverage > 75%) ✅ No empty test files ✅ All tests pass on main branch ✅ Coverage trend is increasing

Anti-Patterns (What We Stop)

❌ Empty test files that "count" toward coverage ❌ Stub tests with no assertions ❌ Mocking the thing you're testing ❌ Tests that pass whether code works or not ❌ Copy-paste tests (unmaintainable) ❌ One giant test file (hard to find issues) ❌ Writing tests after code (finds nothing)


Key Mantra:

"An empty test file is admitting we don't know if it works. Real tests are how we earn the right to claim features are done."

Didn't find tool you were looking for?

Be as detailed as possible for better results