Unit Test Writer

Generates comprehensive unit tests for any function or module with edge cases.

8 stars

Best use case

Unit Test Writer is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Generates comprehensive unit tests for any function or module with edge cases.

Teams using Unit Test Writer should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/unit-test-writer/SKILL.md --create-dirs "https://raw.githubusercontent.com/Notysoty/openagentskills/main/skills/unit-test-writer/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/unit-test-writer/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How Unit Test Writer Compares

Feature / AgentUnit Test WriterStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Generates comprehensive unit tests for any function or module with edge cases.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Unit Test Writer

## What this skill does

This skill directs the agent to write a thorough unit test suite for a given function, class, or module. It systematically identifies happy paths, edge cases, error paths, and boundary conditions — then writes tests in your chosen framework (Jest, Vitest, Mocha, etc.) with proper mocking where needed.

Use this when you have a function that needs test coverage or when you want to verify your implementation handles edge cases you might not have thought of.

## How to use

### Claude Code / Cline

Copy this file to `.agents/skills/unit-test-writer/SKILL.md` in your project root.

Then ask the agent:
- *"Write unit tests for `src/utils/formatCurrency.ts` using the Unit Test Writer skill."*
- *"Use the Unit Test Writer skill to generate Vitest tests for this function."*

Paste the function code into the chat, or reference the file path.

### Cursor

Add the instructions from the "Prompt / Instructions" section below to your `.cursorrules`, or paste them into the Cursor AI pane before asking for tests.

### Codex

Paste your function and the instructions below into the Codex chat. Specify your test framework explicitly (Jest, Vitest, etc.) since Codex does not infer it from the project.

## The Prompt / Instructions for the Agent

When asked to write unit tests, follow these steps:

1. **Read the code.** Understand the function's:
   - Inputs (types, shapes, constraints)
   - Outputs (return type, side effects)
   - Dependencies (external calls, imports that may need mocking)
   - Error conditions (what throws, what returns null/undefined)

2. **Identify test cases in this order:**
   - **Happy path** — typical valid inputs that produce the expected output
   - **Boundary values** — min/max numbers, empty strings, empty arrays, zero
   - **Type coercions** — what happens with `null`, `undefined`, `0`, `""`, `false`
   - **Error paths** — inputs that should throw or return an error state
   - **Async edge cases** (if async) — resolved values, rejected promises, race conditions
   - **Mocked dependencies** — external calls (API, DB, filesystem) must be mocked; never make real calls in unit tests

3. **Structure the test file:**
   - One `describe` block per function or class
   - Nested `describe` blocks for logical groups (e.g., `describe('when user is not logged in', ...)`)
   - Test names must read as complete sentences: `it('returns null when input is an empty array')`
   - Keep each test focused — one assertion per test when possible, or one concept per test

4. **Mocking rules:**
   - Use `jest.mock()` / `vi.mock()` for module-level mocks
   - Use `jest.spyOn()` / `vi.spyOn()` for spying on methods without replacing the module
   - Always restore mocks in `afterEach` or use `clearMocks: true` in config
   - Mock at the boundary — mock the imported module, not internal implementation details

5. **Output format:**

```typescript
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; // or jest equivalents
import { functionUnderTest } from '../path/to/module';

// Mock external dependencies
vi.mock('../path/to/dependency', () => ({
  someFunction: vi.fn(),
}));

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

  describe('happy path', () => {
    it('returns the expected result for valid input', () => {
      // arrange
      // act
      // assert
    });
  });

  describe('edge cases', () => {
    it('returns null when input is an empty array', () => { ... });
    it('handles zero correctly', () => { ... });
  });

  describe('error handling', () => {
    it('throws TypeError when input is not a string', () => { ... });
  });
});
```

6. **After writing the tests**, list any cases you could not cover and why (e.g., untestable private methods, missing type information).

## Example

**Input to Agent:**
> "Use the Unit Test Writer skill to write Vitest tests for this function:
>
> ```typescript
> export function parsePriceString(price: string): number {
>   if (!price || typeof price !== 'string') throw new TypeError('price must be a string');
>   const cleaned = price.replace(/[$,\s]/g, '');
>   const num = parseFloat(cleaned);
>   if (isNaN(num)) throw new RangeError(`Cannot parse price from "${price}"`);
>   return num;
> }
> ```"

**Output from Agent:**
```typescript
import { describe, it, expect } from 'vitest';
import { parsePriceString } from '../utils/parsePriceString';

describe('parsePriceString', () => {
  describe('happy path', () => {
    it('parses a plain number string', () => {
      expect(parsePriceString('9.99')).toBe(9.99);
    });

    it('strips dollar signs', () => {
      expect(parsePriceString('$19.99')).toBe(19.99);
    });

    it('strips commas from large numbers', () => {
      expect(parsePriceString('$1,299.00')).toBe(1299);
    });

    it('strips leading and trailing whitespace', () => {
      expect(parsePriceString('  $5.00  ')).toBe(5);
    });
  });

  describe('edge cases', () => {
    it('handles zero', () => {
      expect(parsePriceString('$0.00')).toBe(0);
    });

    it('handles a string with only a dollar sign as invalid', () => {
      expect(() => parsePriceString('$')).toThrow(RangeError);
    });
  });

  describe('error handling', () => {
    it('throws TypeError when price is not a string', () => {
      expect(() => parsePriceString(null as any)).toThrow(TypeError);
    });

    it('throws TypeError when price is undefined', () => {
      expect(() => parsePriceString(undefined as any)).toThrow(TypeError);
    });

    it('throws TypeError when price is an empty string', () => {
      expect(() => parsePriceString('')).toThrow(TypeError);
    });

    it('throws RangeError when string contains no numeric characters', () => {
      expect(() => parsePriceString('abc')).toThrow(RangeError);
    });
  });
});
```

## Notes

- Always specify your test framework. The skill defaults to Vitest syntax, but will adapt to Jest, Mocha, or others on request.
- If the function has many external dependencies, ask the agent to list the mocks it would need before writing the full suite.
- This skill writes the test file only — it does not modify the source file.
- For very large modules, ask for tests one exported function at a time.

Related Skills

Unit Test Improver

8
from Notysoty/openagentskills

Reviews existing unit tests for gaps, weak assertions, and missing edge cases, then rewrites them to be more robust.

Technical Blog Post Writer

8
from Notysoty/openagentskills

Writes engaging, accurate technical blog posts targeted at developer audiences.

Social Post Thread Writer

8
from Notysoty/openagentskills

Converts a blog post, idea, or document into an engaging Twitter/X or LinkedIn thread with hooks and CTAs.

SDK Quickstart Writer

8
from Notysoty/openagentskills

Generates a concise, copy-paste-ready quickstart guide for any SDK or library.

README Writer

8
from Notysoty/openagentskills

Generates a professional, comprehensive README.md for any project from its codebase or description.

PR Description Writer

8
from Notysoty/openagentskills

Writes clear, thorough pull request descriptions from a diff or list of changes.

Playwright Test Builder

8
from Notysoty/openagentskills

Generates robust Playwright end-to-end tests for web pages and user flows.

Newsletter Summary Writer

8
from Notysoty/openagentskills

Condenses long articles, threads, or documents into concise, engaging newsletter-ready summaries.

Migration Guide Writer

8
from Notysoty/openagentskills

Writes clear migration guides for library upgrades, breaking API changes, or framework version bumps.

Incident Postmortem Writer

8
from Notysoty/openagentskills

Writes a blameless incident postmortem document from an incident timeline or Slack thread.

Git Commit Writer

8
from Notysoty/openagentskills

Generates conventional commit messages from staged changes or a diff.

Flaky Test Analyzer

8
from Notysoty/openagentskills

Diagnoses why tests pass inconsistently and suggests fixes for timing, ordering, and state isolation issues.