AI-Assisted Testing & Tools

AI Test Generation: Tools and Techniques

Use AI tools to generate comprehensive test suites — and know what to review and add yourself.

AI Test Generation: The State of the Art

AI tools can generate test code significantly faster than humans. The key is knowing how to prompt them effectively and what to review carefully.

Tools for AI test generation:

  • Claude Code / Claude — Generate tests from function signatures and behavior descriptions
  • Cursor — Inline test generation with context awareness across your codebase
  • GitHub Copilot — Auto-complete test patterns as you type
  • CodiumAI — Dedicated test generation tool that analyzes your code and generates suites

Effective Prompting

The quality of generated tests depends almost entirely on the quality of your prompt:

text
Weak prompt: "Write tests for the login function"

Strong prompt:
"Write Vitest tests for this TypeScript function:

async function login(email: string, password: string): Promise<{ token: string; user: User }>

text

The function should:
- Return a JWT token and user object on success
- Throw 'Invalid credentials' for wrong password
- Throw 'Account locked' after 5 failed attempts (tracked in Redis)
- Throw 'Email not verified' for unverified accounts
- Accept both email and username formats

Use Vitest with vi.mock() for the database and Redis.
Cover: success case, wrong password, locked account, unverified, and multiple rapid failures."

What AI Does Well

  • Generating happy-path tests quickly
  • Creating test boilerplate (describe/it structure, imports, setup)
  • Catching obvious edge cases (null inputs, empty arrays, empty strings, boundary values)
  • Following testing patterns from existing tests in the codebase

What AI Misses (Always Add These)

typescript
// AI usually covers:
it('returns user for valid credentials', ...)
it('throws for invalid password', ...)

// AI often misses:
it('does not expose password hash in response', ...) // Security
it('sanitizes HTML in user-provided name field', ...) // XSS prevention
it('handles concurrent login attempts correctly', ...) // Race conditions
it('rate limits login attempts per IP', ...) // Business rule
it('logs failed login attempts for security audit', ...) // Compliance

Review Checklist for AI-Generated Tests

Before accepting AI-generated tests, verify:

Tests behavior, not implementation — Does the test care about internal state or external behavior?

Assertions are meaningfulexpect(result).toBeDefined() is almost never a good assertion. What specifically should be defined?

Error paths are covered — AI focuses on happy paths. Find and test every error condition.

Security checks are present — Does the test verify that sensitive data is NOT exposed? That unauthorized users are blocked?

A bug would actually fail this test — For each test, ask: "If there were a bug in the implementation, would this catch it?"

Iterating with AI

AI-generated tests are a starting point, not a final product:

text
Initial: "Write tests for the createOrder function"

Review: "Tests don't cover the case where item is out of stock. Add that."

Review: "Tests don't verify that the order confirmation email is sent. Add that."

Review: "Tests should verify that the user's cart is cleared after successful order. Add that."

Each feedback cycle improves the test coverage.

Key Takeaways

  • AI generates tests faster when given precise, detailed prompts — include function signature, all behaviors, and edge cases
  • AI excels at happy-path tests and boilerplate; humans must add security checks, race conditions, and domain-specific edge cases
  • The review checklist: behavior not implementation, meaningful assertions, error paths, security, and causality (would a bug fail this?)
  • Treat AI-generated tests as a first draft — expect to add 20-40% more test cases yourself
  • The most valuable AI test generation workflow: you write the spec, AI generates tests, you review and augment

Example

typescript
// Effective prompt for AI test generation
// Input to AI:
/**
 * Generate Vitest tests for:
 *
 * function slugify(text: string): string
 *
 * Behaviors:
 * - Converts to lowercase
 * - Replaces spaces with hyphens
 * - Removes special characters (keep letters, numbers, hyphens)
 * - Trims leading/trailing hyphens
 * - Collapses multiple hyphens into one
 * - Returns empty string for empty input
 * - Throws TypeError for non-string input
 *
 * Use Vitest describe/it/expect format.
 */

// AI generates:
describe('slugify', () => {
  it('converts to lowercase', () => {
    expect(slugify('Hello World')).toBe('hello-world');
  });

  it('replaces spaces with hyphens', () => {
    expect(slugify('my great post')).toBe('my-great-post');
  });

  it('removes special characters', () => {
    expect(slugify('Hello, World!')).toBe('hello-world');
  });

  it('trims leading/trailing hyphens', () => {
    expect(slugify('  hello  ')).toBe('hello');
  });

  it('collapses multiple hyphens', () => {
    expect(slugify('hello---world')).toBe('hello-world');
  });

  it('returns empty string for empty input', () => {
    expect(slugify('')).toBe('');
  });

  it('throws TypeError for non-string input', () => {
    expect(() => slugify(123 as any)).toThrow(TypeError);
  });
});
Try it yourself — TYPESCRIPT