agentsclimarketplace

Test levels

Skill georgekhananaev/claude-skills-vault/.claude/skills/test-levels

A curated collection of high impact skills for Claude Code designed to supercharge the senior full stack workflow. This vault automates the repetitive parts of development like architectural reviews, TDD cycles, and PR management so you can stay in flow. It is a force multiplier for shipping clean, production ready code at scale. πŸš€βš‘οΈ

Install
npx -y skills add georgekhananaev/claude-skills-vault --skill test-levels

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

What its author says it does

Copied from the file, not written here

This skill explains the 3 test levels (Unit, Integration, E2E) using the "Building a Car" analogy and provides guidance on when to use each type. Includes project-specific Playwright examples.

SKILL.md

6.8 KB, as published. Nobody here has run it

Test Levels Guide

Explains test types & guides test selection using car analogy.

When to Use

Invoke when:

  • Explaining test concepts to team members
  • Deciding which test type to write
  • Reviewing test coverage strategy
  • Onboarding new developers to testing

The 3 Test Levels

1. Unit Test (Test Case)

The specific instruction.

Single fn/component tested in isolation. No external deps (DB, API, browser).

AspectDescription
Analogy"Check if left turn signal blinks when I push lever down"
ScopeTiny detail - one fn, one input/output
SpeedFast (ms)
Locationtests/unit/

When to write:

  • Pure functions (formatters, validators, utils)
  • Data transformations
  • Business logic w/o side effects

Project example:

// tests/unit/utils/formatters.spec.ts
import {expect, test} from 'next/experimental/testmode/playwright';
import {leadingZero, formatCurrency} from '@/app/_utils/formatters';

test.describe('formatters', () => {
    test('leadingZero adds zero to single-digit numbers', () => {
        expect(leadingZero(7)).toBe('07');
        expect(leadingZero(10)).toBe('10');
    });

    test('formatCurrency formats correctly', () => {
        const result = formatCurrency({value: 1234.56, locale: 'en', currency: 'USD'});
        expect(result).toBe('1,234.56 $');
    });
});

2. Integration Test

The handshake.

Tests if 2+ parts communicate correctly. Focuses on connections, not full system.

AspectDescription
Analogy"Does engine make wheels turn?" (Engine β†’ Transmission)
ScopeConnections between components
SpeedMedium (100ms-few seconds)
Locationtests/integration/

When to write:

  • Validators w/ schemas (Zod)
  • API route handlers
  • Service-to-service communication
  • DB queries w/ mocked data

Project example:

// tests/integration/validators/offer.spec.ts
import {expect, test} from 'next/experimental/testmode/playwright';
import {mockLoggedUser} from '../../common';
import {validateCustomerStatus} from '@/app/_lib/validator';

test.beforeEach(async ({context}) => {
    await mockLoggedUser(context);
});

test.describe('validate customer status', () => {
    const validData = {
        offerId: '670e80f0a65da593d265088a',
        status: 'viewing',
    };

    test('returns success for valid data', async () => {
        const result = validateCustomerStatus(validData);
        expect(result.success).toBe(true);
        expect(result.data).toEqual(validData);
    });

    test('returns error for invalid offerId', async () => {
        const result = validateCustomerStatus({...validData, offerId: ''});
        expect(result.success).toBe(false);
        expect(result.error?.issues[0]?.path).toContain('offerId');
    });
});

3. E2E Test (End-to-End)

The real user journey.

Full system test: browser, DB, network, 3rd-party services. Exactly as user experiences.

AspectDescription
Analogy"Start car, drive to store, park, turn off"
ScopeFull user flow
SpeedSlow (seconds-minutes)
Locationtests/pages/

When to write:

  • Critical user flows (login, checkout, payment)
  • Multi-page journeys
  • Features requiring browser interaction
  • Smoke tests for deployment

Project example:

// tests/pages/start.spec.ts
import {expect, test} from 'next/experimental/testmode/playwright';
import {mockLoggedUser, resetAPIEndpointsMock} from '../common';

test.beforeEach(async ({context}) => {
    await mockLoggedUser(context);
});

test.afterEach(async ({next, context}) => {
    await resetAPIEndpointsMock(next);
    await context.clearCookies();
});

test('start page renders correctly', async ({page}) => {
    test.setTimeout(120000);

    await page.goto('http://localhost:3000/start', {
        timeout: 90000,
        waitUntil: 'domcontentloaded'
    });

    await expect(page).toHaveURL('http://localhost:3000/start');
    await expect(page.getByTestId('pageHeader')).toHaveClass('drop-shadow-font');
    await expect(page.getByTestId('subTotal')).toContainText('Sub total');
    await expect(page.getByTestId('startCounter')).toContainText('Your vacation starts in');
});

Quick Decision Guide

QuestionTest Type
"Does this fn return correct value?"Unit
"Do these 2 parts work together?"Integration
"Does full flow work for user?"E2E

Test Pyramid

        /\
       /E2E\         Few (slow, expensive)
      /------\
     /Integr- \      Some (medium)
    /  ation   \
   /------------\
  /    Unit      \   Many (fast, cheap)
 /________________\

Rule: More unit tests, fewer E2E tests. Unit tests catch bugs early & run fast.


Project Structure

tests/
β”œβ”€β”€ unit/              # Pure fn tests (no browser)
β”‚   └── utils/         # Utility fn tests
β”œβ”€β”€ integration/       # Component interaction tests
β”‚   β”œβ”€β”€ validators/    # Schema validation tests
β”‚   └── lib/           # Library fn tests
β”œβ”€β”€ pages/             # E2E browser tests
β”‚   β”œβ”€β”€ start.spec.ts
β”‚   β”œβ”€β”€ payment.spec.ts
β”‚   └── confirm.spec.ts
β”œβ”€β”€ common.ts          # Shared test utilities
β”œβ”€β”€ mock/              # Mock data & helpers
└── seed.spec.ts       # DB seed for tests

Commands

# Run all tests (headed mode)
npm run test

# Run specific test file
npm run test tests/unit/utils/formatters.spec.ts

# Run tests in UI mode
npm run test:ui

# Show test report
npm run test:report

Best Practices

  1. Name tests clearly: should [action] when [condition]
  2. One assertion focus: Test one behavior per test
  3. Use test.describe: Group related tests
  4. Clean up: Use afterEach for state reset
  5. Mock external deps: Use mockLoggedUser, resetAPIEndpointsMock
  6. Set timeouts: E2E tests need longer timeouts (120s)
  7. Use data-testid: For reliable element selection

Summary Table

LevelQuestionScopeSpeedLocation
Unit"Does this fn work?"Single fnFasttests/unit/
Integration"Do parts connect?"ConnectionsMediumtests/integration/
E2E"Does flow work?"Full systemSlowtests/pages/

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.