test-automation-expert

Test Automation Expert

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "test-automation-expert" with this command: npx skills add curiositech/some_claude_skills/curiositech-some-claude-skills-test-automation-expert

Test Automation Expert

Comprehensive testing guidance from unit to E2E. Designs test strategies, implements automation, and optimizes coverage for sustainable quality.

When to Use

Use for:

  • Designing test strategy for new projects

  • Setting up testing frameworks (Jest, Vitest, Playwright, Cypress, pytest)

  • Writing effective unit, integration, and E2E tests

  • Optimizing test coverage and eliminating gaps

  • Debugging flaky tests

  • CI/CD test pipeline configuration

  • Test-Driven Development (TDD) guidance

  • Mocking strategies and test fixtures

Do NOT use for:

  • Manual QA test case writing - this is automation-focused

  • Load/performance testing - use performance-engineer skill

  • Security testing - use security-auditor skill

  • API contract testing only - use backend-architect for API design

Test Pyramid Philosophy

     /\
    /  \      E2E Tests (10%)
   /----\     - Critical user journeys
  /      \    - Cross-browser validation
 /--------\
/          \  Integration Tests (20%)

/ \ - API contracts /--------------- Component interactions /
/------------------\ Unit Tests (70%) - Fast, isolated, deterministic - Business logic validation

Distribution Guidelines

Test Type Percentage Execution Time Purpose

Unit 70% < 100ms each Logic validation

Integration 20% < 1s each Component contracts

E2E 10% < 30s each Critical paths

Framework Selection

JavaScript/TypeScript

Framework Best For Speed Config Complexity

Vitest Vite projects, modern ESM Fastest Low

Jest React, established projects Fast Medium

Playwright E2E, cross-browser N/A Low

Cypress E2E, component testing N/A Medium

Python

Framework Best For Speed Features

pytest Everything Fast Fixtures, plugins

unittest Standard library Medium Built-in

hypothesis Property-based Varies Generative

Decision Tree: Framework Selection

New project? ├── Yes → Using Vite? │ ├── Yes → Vitest │ └── No → Jest or Vitest (both work) └── No → What exists? ├── Jest → Keep Jest (migration cost rarely worth it) ├── Mocha → Consider migration to Vitest └── Nothing → Vitest (modern default)

Need E2E? ├── Cross-browser critical → Playwright ├── Developer experience priority → Cypress └── Both → Playwright (more flexible)

Unit Testing Patterns

Good Unit Test Anatomy

describe('UserService', () => { describe('validateEmail', () => { // Arrange-Act-Assert pattern it('should accept valid email formats', () => { // Arrange const validEmails = ['user@example.com', 'name+tag@domain.co'];

  // Act &#x26; Assert
  validEmails.forEach(email => {
    expect(validateEmail(email)).toBe(true);
  });
});

it('should reject invalid email formats', () => {
  // Arrange
  const invalidEmails = ['invalid', '@missing.com', 'no@tld'];

  // Act &#x26; Assert
  invalidEmails.forEach(email => {
    expect(validateEmail(email)).toBe(false);
  });
});

// Edge cases explicitly tested
it('should handle empty string', () => {
  expect(validateEmail('')).toBe(false);
});

it('should handle null/undefined', () => {
  expect(validateEmail(null)).toBe(false);
  expect(validateEmail(undefined)).toBe(false);
});

}); });

Mocking Strategies

// ✅ Good: Mock at boundaries jest.mock('../services/api', () => ({ fetchUser: jest.fn() }));

// ✅ Good: Explicit mock setup per test beforeEach(() => { fetchUser.mockReset(); });

it('handles user not found', async () => { fetchUser.mockRejectedValue(new NotFoundError()); await expect(getUser(123)).rejects.toThrow('User not found'); });

// ❌ Bad: Mocking implementation details jest.mock('../utils/internal-helper'); // Don't mock internals

Test Isolation Checklist

  • Each test can run independently

  • No shared mutable state between tests

  • Database/API state reset between tests

  • No test order dependencies

  • Parallel execution safe

Integration Testing Patterns

API Integration Test

describe('POST /api/users', () => { let app; let db;

beforeAll(async () => { db = await createTestDatabase(); app = createApp({ db }); });

afterAll(async () => { await db.close(); });

beforeEach(async () => { await db.clear(); });

it('creates user with valid data', async () => { const response = await request(app) .post('/api/users') .send({ name: 'Test', email: 'test@example.com' }) .expect(201);

expect(response.body).toMatchObject({
  id: expect.any(String),
  name: 'Test',
  email: 'test@example.com'
});

// Verify side effects
const dbUser = await db.users.findById(response.body.id);
expect(dbUser).toBeDefined();

});

it('rejects duplicate email', async () => { await db.users.create({ name: 'Existing', email: 'test@example.com' });

await request(app)
  .post('/api/users')
  .send({ name: 'New', email: 'test@example.com' })
  .expect(409);

}); });

Component Integration (React)

import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { UserProfile } from './UserProfile'; import { UserProvider } from '../context/UserContext';

describe('UserProfile integration', () => { it('loads and displays user data', async () => { render( <UserProvider> <UserProfile userId="123" /> </UserProvider> );

// Verify loading state
expect(screen.getByRole('progressbar')).toBeInTheDocument();

// Wait for data
await waitFor(() => {
  expect(screen.getByText('John Doe')).toBeInTheDocument();
});

// Verify loaded state
expect(screen.queryByRole('progressbar')).not.toBeInTheDocument();

}); });

E2E Testing Patterns

Playwright Best Practices

import { test, expect } from '@playwright/test';

test.describe('Checkout Flow', () => { test.beforeEach(async ({ page }) => { // Seed test data via API await page.request.post('/api/test/seed', { data: { scenario: 'checkout-ready' } }); });

test('complete purchase with credit card', async ({ page }) => { await page.goto('/cart');

// Use accessible selectors
await page.getByRole('button', { name: 'Proceed to checkout' }).click();

// Fill payment form
await page.getByLabel('Card number').fill('4242424242424242');
await page.getByLabel('Expiry').fill('12/25');
await page.getByLabel('CVC').fill('123');

// Complete purchase
await page.getByRole('button', { name: 'Pay now' }).click();

// Verify success
await expect(page.getByRole('heading', { name: 'Order confirmed' })).toBeVisible();
await expect(page.getByText(/Order #\d+/)).toBeVisible();

});

test('shows error for declined card', async ({ page }) => { await page.goto('/checkout');

// Use test card that triggers decline
await page.getByLabel('Card number').fill('4000000000000002');
await page.getByLabel('Expiry').fill('12/25');
await page.getByLabel('CVC').fill('123');

await page.getByRole('button', { name: 'Pay now' }).click();

await expect(page.getByRole('alert')).toContainText('Card declined');

}); });

Flaky Test Detection & Prevention

Common Causes:

  • Race conditions in async operations

  • Time-dependent tests

  • Shared state between tests

  • Network variability

  • Animation/transition timing

Fixes:

// ❌ Bad: Fixed timeout await page.waitForTimeout(2000);

// ✅ Good: Wait for specific condition await expect(page.getByText('Loaded')).toBeVisible();

// ❌ Bad: Checking exact time expect(new Date()).toEqual(specificDate);

// ✅ Good: Mock time jest.useFakeTimers(); jest.setSystemTime(new Date('2024-01-15'));

// ❌ Bad: Depending on animation completion await page.click('.button'); expect(await page.isVisible('.modal')).toBe(true);

// ✅ Good: Wait for animation await page.click('.button'); await expect(page.locator('.modal')).toBeVisible();

Coverage Optimization

What to Measure

Metric Target Priority

Line coverage 80%+ Medium

Branch coverage 75%+ High

Function coverage 90%+ Medium

Critical path coverage 100% Critical

Coverage Configuration

// vitest.config.js export default defineConfig({ test: { coverage: { provider: 'v8', reporter: ['text', 'json', 'html'], exclude: [ 'node_modules/', 'test/', '/*.d.ts', '/.config.', '**/index.ts', // barrel files ], thresholds: { branches: 75, functions: 80, lines: 80, statements: 80 } } } });

Finding Coverage Gaps

Generate detailed coverage report

npx vitest run --coverage

Find untested files

npx vitest run --coverage --reporter=json | jq '.coverageMap | to_entries | map(select(.value.s | values | any(. == 0))) | .[].key'

CI/CD Integration

GitHub Actions

name: Tests on: [push, pull_request]

jobs: unit-tests: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' - run: npm ci - run: npm test -- --coverage - uses: codecov/codecov-action@v4

e2e-tests: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 - run: npm ci - run: npx playwright install --with-deps - run: npm run test:e2e - uses: actions/upload-artifact@v4 if: failure() with: name: playwright-report path: playwright-report/

Test Parallelization

// vitest.config.js - parallel by default export default defineConfig({ test: { pool: 'threads', poolOptions: { threads: { singleThread: false } } } });

// playwright.config.js export default defineConfig({ workers: process.env.CI ? 2 : undefined, fullyParallel: true });

Anti-Patterns

Anti-Pattern: Testing Implementation Details

What it looks like:

// ❌ Testing internal state expect(component.state.isLoading).toBe(true);

// ❌ Testing private methods expect(service._calculateHash()).toBe('abc123');

Why wrong: Couples tests to implementation, breaks on refactors

Instead:

// ✅ Test observable behavior expect(screen.getByRole('progressbar')).toBeInTheDocument();

// ✅ Test public interface expect(service.getHash()).toBe('abc123');

Anti-Pattern: Over-Mocking

What it looks like:

// ❌ Mocking everything jest.mock('../utils/format'); jest.mock('../utils/validate'); jest.mock('../utils/transform');

Why wrong: Tests pass even when real code is broken

Instead: Mock only at system boundaries (APIs, databases, external services)

Anti-Pattern: Flaky Acceptance

What it looks like: "That test is just flaky, skip it"

Why wrong: Flaky tests indicate real problems (race conditions, timing issues)

Instead: Fix the flakiness or quarantine while fixing

Anti-Pattern: Coverage Theater

What it looks like:

// ❌ Testing for coverage, not behavior it('covers the function', () => { myFunction(); // No assertions! });

Why wrong: 100% coverage with 0% confidence

Instead: Every test should assert meaningful behavior

Quick Commands

Run all tests

npm test

Run with coverage

npm test -- --coverage

Run specific file

npm test -- src/utils/format.test.ts

Run in watch mode

npm test -- --watch

Run E2E tests

npx playwright test

Run E2E with UI

npx playwright test --ui

Debug E2E test

npx playwright test --debug

Update snapshots

npm test -- -u

Reference Files

  • references/test-strategy.md

  • Comprehensive test strategy framework

  • references/framework-comparison.md

  • Detailed framework comparison

  • references/coverage-patterns.md

  • Coverage optimization techniques

  • references/ci-integration.md

  • CI/CD pipeline configurations

Covers: Test strategy | Unit testing | Integration testing | E2E testing | Coverage | CI/CD | Flaky test debugging

Use with: security-auditor (security tests) | performance-engineer (load tests) | code-reviewer (test quality)

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Automation

test-automation-expert

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

chatbot-analytics

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

agent-creator

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

dag-task-scheduler

No summary provided by upstream source.

Repository SourceNeeds Review