Writing Tests with Claude Code

Tests are code that checks your other code. A test runs a function, gives it some input, and verifies the output matches what you expected. Tests catch bugs before your users do. Claude Code writes tests quickly, covers edge cases you might forget, and explains the testing logic so you understand what each test does.

Why Tests Matter

Imagine building a bridge and never testing its weight limit. You assume it holds, but you do not know. Software without tests works the same way — it runs until something unexpected breaks it.

Without tests:              With tests:
────────────────            ────────────────────────
Write code                  Write code
   ↓                           ↓
Ship it                     Run tests
   ↓                           ↓
User finds bug              Tests fail → you find bug
   ↓                           ↓
Fix in production           Fix before shipping
(expensive, embarrassing)   (cheap, private)

Types of Tests Claude Code Can Write

Unit Tests

A unit test checks a single function or small piece of logic in isolation. It is the most common type of test and the easiest to write with Claude.

Function: calculateDiscount(price, percent)
Unit test checks:
  ✓ 10% off $100 returns $90
  ✓ 0% off $100 returns $100
  ✓ 100% off $100 returns $0
  ✓ Negative percent throws an error

Integration Tests

An integration test checks how two or more pieces of your system work together. For example, testing whether your API endpoint correctly reads from and writes to the database.

End-to-End Tests

An end-to-end test simulates a real user action from start to finish — clicking a button, filling a form, and verifying the right data appears on screen. These take longer to run but catch problems that unit tests miss.

┌────────────────────────────────────────┐
│         TEST PYRAMID                   │
│                                        │
│              /\                        │
│             /E2E\   ← Few, slow, broad │
│            /──────\                    │
│           /Integra-\← Some, medium     │
│          /  tion    \                  │
│         /────────────\                 │
│        /  Unit Tests  \ ← Many, fast   │
│       /────────────────\               │
└────────────────────────────────────────┘

Asking Claude Code to Write Tests

The best approach is to paste your existing function and ask Claude to write tests for it. Give Claude the testing framework you use so it writes tests in the right format.

Basic Test Request

"Write unit tests for this function using Jest.
Cover normal cases, edge cases, and error cases.

[paste your function here]"

Specific Framework Request

"Write tests for this Python function using pytest.
I want at least one test for each of these scenarios:
- valid input
- empty string input
- input over 100 characters
- special characters in input"

A Complete Example: Function to Tests

Your Function (JavaScript)

function splitBill(total, people) {
  if (people <= 0) throw new Error("Need at least one person");
  if (total < 0) throw new Error("Total cannot be negative");
  return parseFloat((total / people).toFixed(2));
}

Prompt to Claude

"Write Jest unit tests for the splitBill function above.
Cover: normal split, single person, zero total,
negative total, and non-integer results."

Claude's Output

describe('splitBill', () => {
  test('splits equally among 4 people', () => {
    expect(splitBill(100, 4)).toBe(25.00);
  });

  test('works with a single person', () => {
    expect(splitBill(75, 1)).toBe(75.00);
  });

  test('handles zero total', () => {
    expect(splitBill(0, 3)).toBe(0.00);
  });

  test('rounds to 2 decimal places', () => {
    expect(splitBill(10, 3)).toBe(3.33);
  });

  test('throws when people is zero', () => {
    expect(() => splitBill(100, 0)).toThrow("Need at least one person");
  });

  test('throws when total is negative', () => {
    expect(() => splitBill(-50, 2)).toThrow("Total cannot be negative");
  });
});

Test-Driven Development With Claude Code

Test-Driven Development (TDD) means writing tests before you write the function. You define what the function should do, write a failing test, then build the function until the test passes. Claude Code fits naturally into this workflow.

TDD Flow with Claude

STEP 1: Describe to Claude what the function should do
        ↓
STEP 2: Ask Claude to write tests for that behavior
        ↓
STEP 3: Run the tests — they all fail (expected)
        ↓
STEP 4: Ask Claude to write the function that passes them
        ↓
STEP 5: Run the tests — they should all pass
        ↓
STEP 6: Refactor the function — tests keep it honest

TDD Prompt Example

"I need a function called `validateEmail(email)`.
It should return true for valid email addresses and
false for invalid ones. Write Jest tests for it first,
before we write the function."

Claude writes the tests. You run them — they fail because the function does not exist yet. Then you ask Claude to write the function. The tests tell you when it works correctly.

Asking Claude to Find Missing Test Cases

Even if you already have some tests, Claude can spot the gaps. Paste your existing tests and ask what is missing.

Prompt:
"Here are my current tests for the parseDate function.
What important cases am I NOT testing?

[paste your existing tests]"

Claude will list things like: leap year dates, invalid month numbers, empty string input, dates in different locales, and future dates versus past dates. These are the edge cases that cause real-world bugs.

Generating Test Data

Tests need realistic data. Claude Code generates test data sets quickly, including tricky edge cases you might overlook.

Prompt:
"Generate 10 test cases for a phone number validator.
Include valid numbers from different countries,
numbers that are too short, too long, and ones with
special characters."

Mocking Dependencies in Tests

Real functions often depend on a database, an API, or a third-party service. Tests should not call real databases — that makes them slow and fragile. Instead, you use mocks: fake versions of those dependencies that return controlled responses.

Claude Code writes mocks for you when you describe what needs to be faked.

Prompt:
"This function calls a payment API to process a charge.
Write Jest tests with a mock for the payment API.
Test: successful charge, declined card, and network error."
What mocking looks like:
────────────────────────────────────────────
Real code:  processPayment() → calls Stripe API → gets real response
Mock code:  processPayment() → calls fake Stripe → returns fake response

Your test controls the fake response, so you can test
error paths without spending real money or hitting real servers.

Running and Reading Test Results

After Claude writes your tests, you run them in the terminal. Most JavaScript projects use npm test. Python projects use pytest. Reading the results tells you what passed and what failed.

Test result output:
──────────────────────────────────
✓ splits equally among 4 people    (3ms)
✓ works with a single person       (1ms)
✓ handles zero total               (1ms)
✓ rounds to 2 decimal places       (2ms)
✗ throws when people is zero       FAILED

Expected error: "Need at least one person"
Received: TypeError: Cannot divide by zero
──────────────────────────────────
Tests: 1 failed, 4 passed

When a test fails, paste the error output into Claude Code and ask what went wrong. Claude reads the failure message, identifies the cause, and suggests a fix.

Keeping Tests Maintainable

Tests need maintenance just like the code they test. When you change a function, some tests will break. Ask Claude to update the tests to match the new behavior.

Prompt:
"I changed the splitBill function to also accept a
tip percentage parameter. Update the tests to cover this."

Key Points

  • Unit tests check individual functions; integration tests check how pieces work together; end-to-end tests check full user flows
  • Give Claude your function, your framework name, and a list of scenarios to get precise tests
  • Test-Driven Development means writing tests before writing the function — Claude fits cleanly into this workflow
  • Ask Claude to find gaps in your existing tests — it spots edge cases like empty input, null values, and boundary numbers
  • Use mocks for external dependencies like databases, APIs, and payment services so tests run fast and reliably
  • Paste failing test output into Claude to diagnose and fix failures quickly

Leave a Comment