testing-strategies

Comprehensive testing strategy design covering unit, integration, E2E testing, and TDD practices. Implements test pyramid structure with recommended ratios: 70% unit tests, 20% integration, 10% E2E tests Provides Given-When-Then patterns for unit testing, mocking strategies for external dependencies, and API endpoint testing examples Includes E2E testing guidance using Playwright for complete user flow validation and TDD red-green-refactor cycle methodology Covers CI/CD integration, test isolation requirements, and best practices including AAA pattern, deterministic tests, and edge case handling

INSTALLATION
npx skills add https://github.com/supercent-io/skills-template --skill testing-strategies
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

Testing Strategies

When to use this skill

  • New project: define a testing strategy
  • Quality issues: bugs happen frequently
  • Before refactoring: build a safety net
  • CI/CD setup: automated tests

Instructions

Step 1: Understand the Test Pyramid

/\

      /E2E\          ← few (slow, expensive)

     /______\

    /        \

   /Integration\    ← medium

  /____________\

 /              \

/   Unit Tests   \  ← many (fast, inexpensive)

/________________\

Ratio guide:

  • Unit: 70%
  • Integration: 20%
  • E2E: 10%

Step 2: Unit testing strategy

Given-When-Then pattern:

describe('calculateDiscount', () => {

  it('should apply 10% discount for orders over $100', () => {

    // Given: setup

    const order = { total: 150, customerId: '123' };

    // When: perform action

    const discount = calculateDiscount(order);

    // Then: verify result

    expect(discount).toBe(15);

  });

  it('should not apply discount for orders under $100', () => {

    const order = { total: 50, customerId: '123' };

    const discount = calculateDiscount(order);

    expect(discount).toBe(0);

  });

  it('should throw error for invalid order', () => {

    const order = { total: -10, customerId: '123' };

    expect(() => calculateDiscount(order)).toThrow('Invalid order');

  });

});

Mocking strategy:

// Mock external dependencies

jest.mock('../services/emailService');

import { sendEmail } from '../services/emailService';

describe('UserService', () => {

  it('should send welcome email on registration', async () => {

    // Arrange

    const mockSendEmail = sendEmail as jest.MockedFunction<typeof sendEmail>;

    mockSendEmail.mockResolvedValueOnce(true);

    // Act

    await userService.register({ email: 'test@example.com', password: 'pass' });

    // Assert

    expect(mockSendEmail).toHaveBeenCalledWith({

      to: 'test@example.com',

      subject: 'Welcome!',

      body: expect.any(String)

    });

  });

});

Step 3: Integration Testing

API endpoint tests:

describe('POST /api/users', () => {

  beforeEach(async () => {

    await db.user.deleteMany();  // Clean DB

  });

  it('should create user with valid data', async () => {

    const response = await request(app)

      .post('/api/users')

      .send({

        email: 'test@example.com',

        username: 'testuser',

        password: 'Password123!'

      });

    expect(response.status).toBe(201);

    expect(response.body.user).toMatchObject({

      email: 'test@example.com',

      username: 'testuser'

    });

    // Verify it was actually saved to the DB

    const user = await db.user.findUnique({ where: { email: 'test@example.com' } });

    expect(user).toBeTruthy();

  });

  it('should reject duplicate email', async () => {

    // Create first user

    await request(app)

      .post('/api/users')

      .send({ email: 'test@example.com', username: 'user1', password: 'Pass123!' });

    // Attempt duplicate

    const response = await request(app)

      .post('/api/users')

      .send({ email: 'test@example.com', username: 'user2', password: 'Pass123!' });

    expect(response.status).toBe(409);

  });

});

Step 4: E2E Testing (Playwright)

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

test.describe('User Registration Flow', () => {

  test('should complete full registration process', async ({ page }) => {

    // 1. Visit homepage

    await page.goto('http://localhost:3000');

    // 2. Click Sign Up button

    await page.click('text=Sign Up');

    // 3. Fill out form

    await page.fill('input[name="email"]', 'test@example.com');

    await page.fill('input[name="username"]', 'testuser');

    await page.fill('input[name="password"]', 'Password123!');

    // 4. Submit

    await page.click('button[type="submit"]');

    // 5. Confirm success message

    await expect(page.locator('text=Welcome')).toBeVisible();

    // 6. Confirm redirect to dashboard

    await expect(page).toHaveURL('http://localhost:3000/dashboard');

    // 7. Confirm user info is displayed

    await expect(page.locator('text=testuser')).toBeVisible();

  });

  test('should show error for invalid email', async ({ page }) => {

    await page.goto('http://localhost:3000/signup');

    await page.fill('input[name="email"]', 'invalid-email');

    await page.fill('input[name="password"]', 'Password123!');

    await page.click('button[type="submit"]');

    await expect(page.locator('text=Invalid email')).toBeVisible();

  });

});

Step 5: TDD (Test-Driven Development)

Red-Green-Refactor Cycle:

// 1. RED: write a failing test

describe('isPalindrome', () => {

  it('should return true for palindrome', () => {

    expect(isPalindrome('racecar')).toBe(true);

  });

});

// 2. GREEN: minimal code to pass the test

function isPalindrome(str: string): boolean {

  return str === str.split('').reverse().join('');

}

// 3. REFACTOR: improve the code

function isPalindrome(str: string): boolean {

  const cleaned = str.toLowerCase().replace(/[^a-z0-9]/g, '');

  return cleaned === cleaned.split('').reverse().join('');

}

// 4. Additional test cases

it('should ignore case and spaces', () => {

  expect(isPalindrome('A man a plan a canal Panama')).toBe(true);

});

it('should return false for non-palindrome', () => {

  expect(isPalindrome('hello')).toBe(false);

});

Output format

Testing strategy document

## Testing Strategy

### Coverage Goals

- Unit Tests: 80%

- Integration Tests: 60%

- E2E Tests: Critical user flows

### Test Execution

- Unit: Every commit (local + CI)

- Integration: Every PR

- E2E: Before deployment

### Tools

- Unit: Jest

- Integration: Supertest

- E2E: Playwright

- Coverage: Istanbul/nyc

### CI/CD Integration

- GitHub Actions: Run all tests on PR

- Fail build if coverage < 80%

- E2E tests on staging environment

Constraints

Required rules (MUST)

  • Test isolation: each test is independent
  • Fast feedback: unit tests should be fast (<1 min)
  • Deterministic: same input → same result

Prohibited items (MUST NOT)

  • Test dependencies: do not let test A depend on test B
  • Production DB: do not use a real DB in tests
  • Sleep/Timeout: avoid time-based tests

Best practices

  • AAA pattern: Arrange-Act-Assert
  • Test names: "should ... when ..."
  • Edge Cases: boundary values, null, empty values
  • Happy Path + Sad Path: both success/failure scenarios

References

Metadata

Version

  • Current version: 1.0.0
  • Last updated: 2025-01-01
  • Compatible platforms: Claude, ChatGPT, Gemini

Related skills

Tags

#testing #test-strategy #TDD #unit-test #integration-test #E2E #code-quality

Examples

Example 1: Basic usage

Example 2: Advanced usage

BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card