59API

← Retour aux guides

AI Unit Tests for Legacy Code: A Practical Guide

Guides · EN · 2026-10-05

Why legacy code needs a careful testing strategy

Legacy code is often difficult to test because it has unclear requirements, hidden dependencies, global state, large functions, and few reliable examples of expected behavior. AI can help generate unit tests quickly, but asking a model to test an entire old system at once usually produces brittle or inaccurate results.

A better approach is to use AI as a testing assistant. You provide a small, understandable unit, explain what must not change, review the generated tests, and run them against the current implementation. The goal is not to make every line look modern. The first goal is to capture behavior that already matters.

1. Start with a testable boundary

Choose a small function or method with a clear input and output. Good starting points include pricing calculations, date formatting, permission checks, parsers, and validation rules. Avoid beginning with a large controller, database service, or function that performs ten unrelated operations.

Before using AI, inspect the function and list its dependencies. Note whether it reads environment variables, accesses a database, calls an HTTP service, writes files, or depends on the current time. This inventory tells you where mocks, fakes, or dependency injection may be needed.

Give the model the implementation, the relevant type definitions, and a short explanation of the surrounding business rule. Do not include credentials, customer data, production logs, or unnecessary parts of the repository.

2. Capture current behavior first

When requirements are missing, ask AI to generate characterization tests. These tests describe what the code does today, including surprising behavior, rather than claiming what the code should do according to an ideal specification.

A useful prompt is: Analyze this function and propose unit tests for normal inputs, boundary values, invalid inputs, and observed side effects. Separate confirmed behavior from assumptions. Use the existing test framework and do not change production code.

Review every expected value. If the model assumes that an empty string is invalid but the current application accepts it, the test may document a guess instead of real behavior. Run the tests against the unmodified code before making refactoring changes.

3. Ask for cases, not just coverage

Line coverage alone does not prove that a test suite is useful. Ask AI to create cases around decisions and failure modes:

For example, a discount function should be tested at the threshold where a discount begins, just below that threshold, and just above it. A date function should include month ends, leap days, and daylight-saving transitions if the product operates across time zones.

4. Make generated tests trustworthy

AI-generated tests need the same review as code written by a developer. Check that assertions verify meaningful outcomes rather than merely confirming that a function was called. Watch for mocks that reproduce the implementation instead of testing it, assertions that are too broad, and tests that pass because exceptions are accidentally swallowed.

Run the suite with the project’s normal command, such as pytest tests/test_orders.py or npm test -- orders, depending on the stack. Then introduce a small, deliberate change to the implementation and confirm that at least one relevant test fails. This mutation-style check exposes tests that provide coverage without protection.

5. Refactor only after behavior is protected

Once characterization tests pass, use AI to suggest small refactors: extracting a pure calculation, passing a clock as a dependency, separating database access from business rules, or reducing a function’s responsibilities. Make one change at a time and rerun the tests after each change.

If a test becomes hard to understand, simplify it manually. A smaller number of precise tests is more valuable than a large generated suite filled with setup noise.

Use affordable AI access for repeated test generation

Generating and reviewing tests can involve many model requests, especially when working through a large legacy repository. 59API is a practical low-cost option because it provides pay-as-you-go access to official-quality Claude models, including Opus, Sonnet, Haiku, and Fable, as well as GPT models. Its API base URL is https://api.59api.com, and it is compatible with Claude Code, Codex, and OpenAI SDK-based tools.

Use a faster, lower-cost model for summarizing files and proposing routine cases, then reserve a stronger model for ambiguous business logic or difficult mocking decisions. 59API also offers a referral rebate, which can reduce costs for teams that regularly use AI during maintenance work. Sign up for 59API when you want an inexpensive way to run this workflow without committing to a large fixed plan.

A repeatable workflow

For each legacy unit, inspect dependencies, ask AI for characterization cases, review assumptions, run tests on unchanged code, and commit the tests separately from refactoring. Track missing scenarios and revisit them when production bugs reveal new behavior. Used this way, AI does not replace engineering judgment. It reduces the mechanical work so you can spend more time deciding which behavior deserves protection.

Tarifs · Docs

Prêt à commencer ?

Connectez Claude et GPT en quelques minutes aux prix les plus bas, sans bridage. Inscrivez-vous pour votre clé API.

Inscription gratuite