testing

SKILL.md

Testing

Roleplay as a testing specialist that designs effective test strategies, writes tests at appropriate layers, and debugs test failures using systematic approaches.

Testing { Activation { Writing unit, integration, or E2E tests Debugging test failures Reviewing test quality Deciding what to mock vs use real implementations }

LayerDistribution { Unit (60-70%) => Mock at boundaries only Integration (20-30%) => Real deps, mock external services only E2E (5-10%) => No mocking - real user journeys }

UnitTests { Purpose: Verify isolated business logic Characteristics: < 100ms, no I/O, deterministic TestHere: Business logic, validation, transformations, edge cases

MockingRules {
  Mock at the edge only (databases, APIs, file system, time)
  Test the real system under test with actual implementations
  Use real internal collaborators - mock only external boundaries
}

Example {
  ```typescript
  // CORRECT: Mock only external dependency
  const service = new OrderService(mockRepository)  // Repository is the edge
  const total = service.calculateTotal(order)
  expect(total).toBe(90)
  
  // WRONG: Mocking internal methods
  vi.spyOn(service, 'applyDiscount')  // Now you're testing the mock
  ```
}

}

IntegrationTests { Purpose: Verify components work together with real dependencies Characteristics: < 5 seconds, containerized deps, clean state between tests TestHere: Database queries, API contracts, service communication, caching

MockingRules {
  Use real databases
  Use real caches
  Mock only external third-party services (Stripe, SendGrid)
}

Example {
  ```typescript
  // CORRECT: Real DB, mock external payment API
  const db = await createTestDatabase()
  const paymentApi = vi.mocked(PaymentGateway)
  const service = new CheckoutService(db, paymentApi)
  
  await service.checkout(cart)
  
  expect(await db.orders.find(orderId)).toBeDefined()  // Real DB
  expect(paymentApi.charge).toHaveBeenCalledOnce()     // Mocked external
  ```
}

}

E2ETests { Purpose: Validate critical user journeys in the real system Characteristics: < 30 seconds, critical paths only, fix flakiness immediately TestHere: Signup, checkout, auth flows, smoke tests

MockingRules {
  No mocking - that's the entire point
  Use real services (sandbox/test modes)
  Real browser automation
}

Example {
  ```typescript
  // Real browser, real system (Playwright example)
  await page.goto('/checkout')
  await page.fill('#card', '4242424242424242')
  await page.click('[data-testid="pay"]')
  
  await expect(page.locator('.confirmation')).toContainText('Order confirmed')
  ```
}

}

CorePrinciples { TestBehaviorNotImplementation { ```typescript // CORRECT: Observable behavior expect(order.total).toBe(108)

  // WRONG: Implementation detail
  expect(order._calculateTax).toHaveBeenCalled()
  ```
}

ArrangeActAssert {
  ```typescript
  // Arrange
  const mockEmail = vi.mocked(EmailService)
  const service = new UserService(mockEmail)
  
  // Act
  await service.register(userData)
  
  // Assert
  expect(mockEmail.sendTo).toHaveBeenCalledWith('user@example.com')
  ```
}

OneBehaviorPerTest => Multiple assertions OK if verifying same logical outcome

DescriptiveNames {
  ```typescript
  // GOOD
  it('rejects order when inventory insufficient', ...)
  
  // BAD
  it('test order', ...)
  ```
}

TestIsolation => No shared mutable state between tests

}

ExecutionOrder { 1. Lint/typecheck => Fastest feedback 2. Unit tests => Fast, high volume 3. Integration tests => Real dependencies 4. E2E tests => Highest confidence }

DebuggingFailures { UnitTestFails { 1. Read the assertion message carefully 2. Check test setup (Arrange section) 3. Run in isolation to rule out state leakage 4. Add logging to trace execution path }

IntegrationTestFails {
  1. Check database state before/after
  2. Verify mocks configured correctly
  3. Look for race conditions or timing issues
  4. Check transaction/rollback behavior
}

E2ETestFails {
  1. Check screenshots/videos (most frameworks capture these)
  2. Verify selectors still match the UI
  3. Add explicit waits for async operations
  4. Run locally with visible browser to observe
  5. Compare CI environment to local
}

}

FlakyTests { HandleAggressively => They erode trust

Protocol {
  1. Quarantine => Move to separate suite immediately
  2. Fix within 1 week => Or delete
}

CommonCauses {
  Shared state between tests
  Time-dependent logic
  Race conditions
  Non-deterministic ordering
}

}

Coverage { Quality over quantity => 80% meaningful coverage beats 100% trivial coverage Focus on business-critical paths (payments, auth, core domain logic) Skip generated code }

EdgeCases { Boundaries => min-1, min, min+1, max-1, max, max+1, zero, one, many SpecialValues => null, empty, negative, MAX_INT, NaN, unicode, leap years, timezones Errors => Network failures, timeouts, invalid input, unauthorized }

AntiPatterns { | Pattern | Problem | | --- | --- | | Over-mocking | Testing mocks instead of code | | Implementation testing | Breaks on refactoring | | Shared state | Test order affects results | | Test duplication | Use parameterized tests instead | } }

References

Weekly Installs
1
First Seen
13 days ago
Installed on
amp1
cline1
opencode1
cursor1
kimi-cli1
codex1