AI-101

Lesson 14

Writing and Running Tests

AI Confidence: 90%

AI-generated

Writing and Running Tests

Learning Objectives

Generate tests for untested code

Run tests and interpret results through Claude Code

Fix failing tests iteratively

Ask for edge case and boundary condition coverage

Use tests as verification for Claude's changes

Introduction

Tests are how you know your code works. They catch bugs before users do. They let you refactor with confidence. They document expected behavior.

Claude Code can write tests for you. It reads your code, understands what it does, and generates test cases that verify correct behavior. It can also run your test suite and fix any failures.

This lesson covers the test writing workflow. You will learn to generate tests, run them, fix failures, and ensure comprehensive coverage. By the end, testing will be a natural part of your Claude Code workflow.

Finding Untested Code

Before writing tests, figure out what needs testing.

Ask Claude to identify gaps:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop
[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop
[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

Claude examines your code and test directories to find gaps.

Check specific files:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop
[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

Once you know what needs tests, you can prioritize.

Generating Tests

Claude Code writes tests that match your project's patterns.

Generate tests for a file:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

Claude reads the payment service, looks at your existing test files to understand patterns, and generates tests that fit.

Generate tests for a function:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

More focused requests get more focused tests.

Match existing patterns:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

Claude examines your test files and replicates the style, assertion library, and organization.

Specify test cases:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

Listing specific cases ensures Claude covers what you care about.

Running Tests

Claude Code can run your test suite and interpret results.

Run all tests:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

Claude executes your test command (npm test, pytest, etc.) and reports results.

Run specific tests:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop
[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

Running specific tests is faster when you are iterating on one area.

Interpret failures:

When tests fail, Claude explains why:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

Claude reads the test, the code, and the error to explain the mismatch.

Fixing Failing Tests

When tests fail, you have two possibilities: the test is wrong, or the code is wrong.

Fix the code:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

Claude reads the failing test, understands what it expects, and modifies the code to match.

Fix the test:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

Sometimes the test's expectation does not match intended behavior. Claude updates the test.

Iterate until green:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

Claude runs tests, fixes issues, runs again, and repeats until all tests pass. You watch and intervene if needed.

Edge Cases and Boundaries

Good tests cover edge cases. Claude can help identify and test them.

Ask for edge cases:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

Claude identifies cases like: empty input, very long input, special characters, null values, network errors.

Generate edge case tests:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

Claude writes tests for boundaries, error conditions, and unusual inputs.

Specific boundary requests:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop
[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

Explicit requests ensure important cases are covered.

Tests as Verification

One of the best uses of tests is verifying Claude's changes work correctly.

Ask Claude to write tests first:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

This is test-driven development (TDD). The test defines success before code is written.

Verify after changes:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

Claude makes the change, runs tests, and reports whether everything still works.

Give Claude a feedback loop:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

When Claude can verify its own work, quality improves significantly. This is the single highest-leverage practice for getting good results from Claude Code.

Test Best Practices

Run tests before and after changes. Know what works before you start. Know nothing broke after you finish.

Test one thing per test. Each test should verify a single behavior. This makes failures clear.

Use descriptive test names. "should return empty array when no users exist" is better than "test1".

Cover the happy path and error paths. Test both what should work and what should fail.

Let Claude match your patterns. Point Claude at existing tests so new ones are consistent.

Practical Testing Workflow

A typical workflow:

Ask Claude what is untested

Pick the most important untested code

Ask Claude to write tests for it

Run the tests

Fix any failures (code or tests)

Repeat until covered

For new features:

Ask Claude to write a failing test

Ask Claude to implement the feature

Run tests to verify

Add edge case tests

Fix any new failures

Key Takeaways

Find untested code by asking Claude to identify gaps

Generate tests that match your project's existing patterns

Run tests through Claude Code and get explanations of failures

Fix code or tests iteratively until everything passes

Ask for edge case coverage explicitly

Use tests as a feedback loop to verify Claude's changes

Try It Yourself

Practice the testing workflow:

Start Claude Code in a project with existing code.

Ask "what code in this project has no tests?"

Pick one untested function and ask Claude to write tests for it.

Run the tests with "run the tests."

If tests fail, ask Claude to explain why and fix the issue.

Ask "what edge cases should I add?"

Add those edge case tests.

Run again to verify everything passes.

This exercise builds your test writing workflow with Claude Code.

Sources

https://code.claude.com/docs/en/common-workflows - Test writing and verification workflows

https://code.claude.com/docs/en/best-practices - Tests as feedback loops

https://code.claude.com/docs/en/quickstart - Running tests through Claude Code