Marketplace

test-generator

Generate comprehensive unit tests for code. Use when creating tests, improving test coverage, or setting up testing frameworks.

allowed_tools: Bash, Read, Write, Grep, Glob

$ Installer

git clone https://github.com/ShunsukeHayashi/Miyabi /tmp/Miyabi && cp -r /tmp/Miyabi/.claude/skills/test-generator ~/.claude/skills/Miyabi

// tip: Run this command in your terminal to install the skill


name: test-generator description: Generate comprehensive unit tests for code. Use when creating tests, improving test coverage, or setting up testing frameworks. allowed-tools: Bash, Read, Write, Grep, Glob

Test Generator

Version: 1.0.0 Purpose: Generate comprehensive tests with high coverage


Triggers

TriggerExamples
Test creation"write tests", "テスト作成", "add unit tests"
Coverage"improve coverage", "カバレッジ向上"
TDD"test first", "TDDで"

Testing Stack

FrameworkPurpose
VitestUnit/Integration tests
PlaywrightE2E tests
Testing LibraryComponent tests

Test Structure (AAA Pattern)

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

    // Act
    const result = functionName(input);

    // Assert
    expect(result).toBe(expectedValue);
  });
});

Test Categories

1. Happy Path

it('should return sum when given valid numbers', () => {
  expect(add(2, 3)).toBe(5);
});

2. Edge Cases

it('should handle empty array', () => {
  expect(sum([])).toBe(0);
});

it('should handle single element', () => {
  expect(sum([5])).toBe(5);
});

it('should handle negative numbers', () => {
  expect(sum([-1, 1])).toBe(0);
});

3. Error Cases

it('should throw on invalid input', () => {
  expect(() => divide(10, 0)).toThrow('Division by zero');
});

it('should throw on null input', () => {
  expect(() => process(null)).toThrow(TypeError);
});

4. Async Tests

it('should fetch user data', async () => {
  const user = await fetchUser(1);
  expect(user.name).toBe('John');
});

it('should handle API errors', async () => {
  await expect(fetchUser(-1)).rejects.toThrow('Not found');
});

Mocking

Mock Functions

import { vi } from 'vitest';

const mockFn = vi.fn();
mockFn.mockReturnValue(42);
mockFn.mockResolvedValue({ data: 'test' });

Mock Modules

vi.mock('./database', () => ({
  query: vi.fn().mockResolvedValue([{ id: 1 }]),
}));

Spies

const spy = vi.spyOn(console, 'log');
doSomething();
expect(spy).toHaveBeenCalledWith('expected message');

Coverage Requirements

MetricTarget
Statements80%
Branches80%
Functions80%
Lines80%
# Run with coverage
npm test -- --coverage

Test File Naming

src/
├── utils/
│   ├── helper.ts
│   └── helper.test.ts      # Co-located
└── __tests__/
    └── integration.test.ts  # Integration tests

Template

import { describe, it, expect, beforeEach, vi } from 'vitest';
import { functionName } from './module';

describe('functionName', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  describe('when input is valid', () => {
    it('should return expected result', () => {
      // Arrange
      const input = { /* ... */ };

      // Act
      const result = functionName(input);

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

  describe('when input is invalid', () => {
    it('should throw error', () => {
      expect(() => functionName(null)).toThrow();
    });
  });

  describe('edge cases', () => {
    it.each([
      [[], 0],
      [[1], 1],
      [[1, 2], 3],
    ])('sum(%j) = %i', (input, expected) => {
      expect(sum(input)).toBe(expected);
    });
  });
});

Checklist

  • All public functions have tests
  • Happy path covered
  • Edge cases covered
  • Error cases covered
  • Async behavior tested
  • Mocks properly cleaned up
  • Coverage meets threshold