Get the FREE Ultimate OpenClaw Setup Guide →

designing-tests

Scanned
npx machina-cli add skill Putra213/claude-workflow-v2/designing-tests --openclaw
Files (1)
SKILL.md
5.3 KB

Designing Tests

Test Implementation Workflow

Copy this checklist and track progress:

Test Implementation Progress:
- [ ] Step 1: Identify what to test
- [ ] Step 2: Select appropriate test type
- [ ] Step 3: Write tests following templates
- [ ] Step 4: Run tests and verify passing
- [ ] Step 5: Check coverage meets targets
- [ ] Step 6: Fix any failing tests

Testing Pyramid

Apply the testing pyramid for balanced coverage:

        /\
       /  \     E2E Tests (10%)
      /----\    - Critical user journeys
     /      \   - Slow but comprehensive
    /--------\  Integration Tests (20%)
   /          \ - Component interactions
  /------------\ - API contracts
 /              \ Unit Tests (70%)
/________________\ - Fast, isolated
                   - Business logic focus

Framework Selection

JavaScript/TypeScript

TypeRecommendedAlternative
UnitVitestJest
IntegrationVitest + MSWJest + SuperTest
E2EPlaywrightCypress
ComponentTesting LibraryEnzyme

Python

TypeRecommendedAlternative
Unitpytestunittest
Integrationpytest + httpxpytest + requests
E2EPlaywrightSelenium
APIpytest + FastAPI TestClient-

Go

TypeRecommended
Unittesting + testify
Integrationtesting + httptest
E2Etesting + chromedp

Test Structure Templates

Unit Test

describe('[Unit] ComponentName', () => {
  describe('methodName', () => {
    it('should [expected behavior] when [condition]', () => {
      // Arrange
      const input = createTestInput();

      // Act
      const result = methodName(input);

      // Assert
      expect(result).toEqual(expectedOutput);
    });

    it('should throw error when [invalid condition]', () => {
      expect(() => methodName(invalidInput)).toThrow(ExpectedError);
    });
  });
});

Integration Test

describe('[Integration] API /users', () => {
  beforeAll(async () => {
    await setupTestDatabase();
  });

  afterAll(async () => {
    await teardownTestDatabase();
  });

  it('should create user and return 201', async () => {
    const response = await request(app)
      .post('/users')
      .send({ name: 'Test', email: 'test@example.com' });

    expect(response.status).toBe(201);
    expect(response.body.id).toBeDefined();
  });
});

E2E Test

describe('[E2E] User Registration Flow', () => {
  it('should complete registration successfully', async ({ page }) => {
    await page.goto('/register');

    await page.fill('[data-testid="email"]', 'new@example.com');
    await page.fill('[data-testid="password"]', 'SecurePass123!');
    await page.click('[data-testid="submit"]');

    await expect(page.locator('.welcome-message')).toBeVisible();
    await expect(page).toHaveURL('/dashboard');
  });
});

Coverage Strategy

What to Cover

  • ✅ Business logic (100%)
  • ✅ Edge cases and error handling (90%+)
  • ✅ API contracts (100%)
  • ✅ Critical user paths (E2E)
  • ⚠️ UI components (snapshot + interaction)
  • ❌ Third-party library internals
  • ❌ Simple getters/setters

Coverage Thresholds

{
  "coverageThreshold": {
    "global": {
      "branches": 80,
      "functions": 80,
      "lines": 80,
      "statements": 80
    },
    "src/core/": {
      "branches": 95,
      "functions": 95
    }
  }
}

Test Data Management

Factories/Builders

// factories/user.js
export const userFactory = (overrides = {}) => ({
  id: faker.string.uuid(),
  name: faker.person.fullName(),
  email: faker.internet.email(),
  createdAt: new Date(),
  ...overrides,
});

// Usage
const admin = userFactory({ role: 'admin' });

Fixtures

// fixtures/users.json
{
  "validUser": { "name": "Test", "email": "test@example.com" },
  "invalidUser": { "name": "", "email": "invalid" }
}

Mocking Strategy

When to Mock

  • ✅ External APIs and services
  • ✅ Database in unit tests
  • ✅ Time/Date for determinism
  • ✅ Random values
  • ❌ Internal modules (usually)
  • ❌ The code under test

Mock Examples

// API mocking with MSW
import { http, HttpResponse } from 'msw';

export const handlers = [
  http.get('/api/users', () => {
    return HttpResponse.json([
      { id: 1, name: 'John' },
    ]);
  }),
];

// Time mocking
vi.useFakeTimers();
vi.setSystemTime(new Date('2024-01-01'));

Test Validation Loop

After writing tests, run this validation:

Test Validation:
- [ ] All tests pass: `npm test`
- [ ] Coverage meets thresholds: `npm test -- --coverage`
- [ ] No flaky tests (run multiple times)
- [ ] Tests are independent (order doesn't matter)
- [ ] Test names clearly describe behavior

If any tests fail, fix them before proceeding. If coverage is below target, add more tests for uncovered code paths.

# Run tests
npm test

# Run with coverage
npm test -- --coverage

# Run specific test file
npm test -- path/to/test.spec.ts

# Run in watch mode during development
npm test -- --watch

Source

git clone https://github.com/Putra213/claude-workflow-v2/blob/main/skills/designing-tests/SKILL.mdView on GitHub

Overview

Designing Tests provides a structured approach to testing any codebase, from unit tests to E2E, including workflow, the Testing Pyramid, framework recommendations, and concrete templates. It guides you in identifying what to test, selecting the right test types, and validating coverage targets to improve quality and reliability.

How This Skill Works

Start by identifying what to test, then select appropriate test types (unit, integration, E2E) and apply the provided templates. Run tests, verify they pass, and ensure coverage meets targets, fixing failures as needed. The approach also maps language-specific recommendations and ready-to-use test structures to speed implementation.

When to Use It

  • When adding tests to a new or existing codebase to establish coverage.
  • When aiming to improve overall test coverage and balance between fast unit tests and slower E2E tests.
  • When setting up or revising testing infrastructure (CI pipelines, MSW, Playwright, Vitest, etc.).
  • When debugging flaky or failing tests and needing structured templates to diagnose.
  • When deciding between unit, integration, and E2E testing to choose the right approach.

Quick Start

  1. Step 1: Identify what to test.
  2. Step 2: Select test types with the Testing Pyramid and language-specific choices.
  3. Step 3: Implement tests using the provided templates, run them, and check coverage.

Best Practices

  • Follow the Test Implementation Progress checklist to stay organized.
  • Apply the Testing Pyramid to prioritize unit tests (70%), integration (20%), and E2E tests (10%).
  • Use language-appropriate templates (Unit/Integration/E2E) to standardize tests.
  • Aim for high coverage on business logic and API contracts, while avoiding testing internals.
  • Use factories/builders for consistent test data and define clear coverage thresholds.

Example Use Cases

  • Unit test for a component method using the [Unit] template.
  • Integration test validating API /users creates a user with 201.
  • E2E test validating user registration flow with Playwright.
  • Test the API contracts using Vitest + MSW.
  • Set up a test database with beforeAll/teardown and verify behavior.

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers