All skills
asyrafhussin avatar

/testing-best-practices

@575c801

Unit testing, integration testing, and test-driven development principles. Use when writing tests, reviewing test code, improving test coverage, or setting up testing strategy. Triggers on "write tests", "review tests", "testing best practices", or "TDD".

Use this Skill: https://skilld.dev/gh/asyrafhussin/agent-skills/testing-best-practices

This session only. Nothing lands on disk.

rulesmock-minimal.md

≈963 tokens on demand. Your agent reads this file only when SKILL.md points to it.

Don't Over-Mock

Impact: MEDIUM (prevents 50% of false-green tests caused by testing implementation details)

Only mock things that are slow, unpredictable, or external. Use real implementations for everything else so refactoring internals doesn't break tests.

Incorrect

// ❌ Bad: mocking every dependency, including simple utilities
import { OrderProcessor } from './order-processor';

vi.mock('./tax-calculator', () => ({
  calculateTax: vi.fn().mockReturnValue(8.5),
}));

vi.mock('./discount-engine', () => ({
  applyDiscount: vi.fn().mockReturnValue(85),
}));

vi.mock('./validators', () => ({
  validateOrder: vi.fn().mockReturnValue(true),
}));

vi.mock('./formatters', () => ({
  formatReceipt: vi.fn().mockReturnValue('Receipt: $93.50'),
}));

describe('OrderProcessor', () => {
  test('processes a valid order', () => {
    const processor = new OrderProcessor();
    const result = processor.process({ items: [{ price: 100 }], discountCode: 'SAVE15' });

    // These tests pass even if the real logic is completely broken
    expect(result.tax).toBe(8.5);
    expect(result.total).toBe(93.5);
    expect(result.receipt).toBe('Receipt: $93.50');
  });

  // After refactoring: merge tax-calculator into discount-engine
  // Result: test breaks because vi.mock('./tax-calculator') fails
  // The behavior is identical, but the test is coupled to file structure
});

Problems:

  • Tests verify mock return values, not real behavior — they always pass regardless of bugs
  • Refactoring internal modules (renaming, merging, splitting files) breaks tests
  • Every mock is a point where the test diverges from production behavior
  • Maintenance burden grows with each unnecessary mock

Correct

// ✅ Good: use real implementations, only mock the external payment API
import { OrderProcessor } from './order-processor';
import { createMockPaymentClient } from '../test-helpers/mock-payment';

describe('OrderProcessor', () => {
  // Only the external payment gateway is mocked
  const mockPaymentClient = createMockPaymentClient();
  const processor = new OrderProcessor(mockPaymentClient);

  test('calculates correct total with tax and discount', () => {
    const result = processor.process({
      items: [{ name: 'Widget', price: 100 }],
      discountCode: 'SAVE15',
      taxRate: 0.085,
    });

    // Real tax calculator, real discount engine, real formatter
    expect(result.subtotal).toBe(100);
    expect(result.discount).toBe(15);
    expect(result.tax).toBe(7.23); // tax on discounted price
    expect(result.total).toBe(92.23);
    expect(result.receipt).toContain('$92.23');
  });

  test('charges payment gateway with final amount', async () => {
    mockPaymentClient.charge.mockResolvedValue({ id: 'txn_1', status: 'paid' });

    const result = await processor.processAndPay({
      items: [{ name: 'Widget', price: 100 }],
      discountCode: 'SAVE15',
      taxRate: 0.085,
    });

    // Only the boundary interaction is verified via mock
    expect(mockPaymentClient.charge).toHaveBeenCalledWith(92.23);
    expect(result.transactionId).toBe('txn_1');
  });

  // After refactoring: merge tax-calculator into discount-engine
  // Result: test still passes because it tests behavior, not file structure
});

Benefits:

  • Real business logic executes, so bugs are caught immediately
  • Refactoring internals (renaming files, extracting functions) never breaks tests
  • Only one mock to maintain instead of four
  • Tests act as a safety net during refactoring, not a barrier

Reference: Testing Implementation Details

Source: SKILL.md on GitHub

No alerts16d5 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    The skill provides comprehensive guidelines and best practices for unit testing, integration testing, and Test-Driven Development (TDD). It consists entirely of documentation and illustrative code examples using industry-standard tools like Jest and Vitest. No security risks or malicious patterns were detected.

  • Socket16d

    No alerts

  • Snyk16d

    Risk: LOW · No issues

  • Runlayer6mo

    29 files scanned · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 575c801. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub last month.

Steadyupdated 7 months ago
metadata
{
  "author": "agent-skills",
  "version": "2.0.0"
}

README badge

README badge for asyrafhussin/agent-skills/testing-best-practices