Write unit tests for legacy code before you change it

Create characterization tests for untested legacy code: lock in current behavior, isolate dependencies like the database or clock and plan a safe step-by-step refactor. Designed for ChatGPT, Claude, Gemini and Microsoft Copilot. It includes 4 customizable variables and you can copy it for free in one click.

Intermediate · Code · Pending editorial review

Prompt

Act as a senior developer experienced in working with legacy code and testing (characterization tests and seams).

Context:
- Language and test framework: {{language}}
- Hard dependencies the code uses (database, current time, network, files, globals): {{dependencies}}
- My goal once tests exist: {{goal}}
- Code:
```
{{code}}
```

Deliverables:
1. A behavior map: inputs, outputs, side effects and code branches, as a short list.
2. Seams: where and how to isolate each dependency with the smallest safe change (parameter injection, wrapping the call, a fake clock) without changing behavior.
3. Characterization tests that lock in the CURRENT behavior, even if it looks wrong. Mark suspicious cases with a "POSSIBLE BUG" comment instead of fixing them.
4. Edge cases: empty, null and extreme values, dependency failures.
5. The branch coverage achieved, what remains uncovered and why.
6. A refactoring plan in small steps, each verifiable with the tests, aimed at {{goal}}.

Constraints:
- Do not change the code's logic in the tests or in the seams.
- Do not invent the expected result of a case if it cannot be derived from the code: mark it [FILL IN: run and paste the real output] and explain how to capture it.
- Use descriptive test names (given / when / then).
- If code the function depends on is missing, ask me for it first.

Format: numbered sections and ready-to-run code blocks.

How to use it

Paste the full function or class and name any external dependencies you know of. Run the tests against the unmodified code: they must all pass before you start refactoring.

Usage example

Language: Python 3.11 with pytest · Dependencies: datetime.now() and MySQL queries · Goal: split a 300-line function that calculates sales commissions.

Sample output

Assuming the full function reads the customer's orders via PDO and uses date() to work out tenure…

2. Seams

  • Database: add an optional ?PDO $pdo = null parameter that falls back to the current connection when null.
  • Date: add ?DateTimeImmutable $now = null and replace date() with $now->format(...).

Both changes leave every existing call site untouched.

3. Characterization tests

<?php
use PHPUnit\Framework\TestCase;

final class CalculateDiscountTest extends TestCase
{
    private PDO $pdo;

    protected function setUp(): void
    {
        $this->pdo = new PDO('sqlite::memory:');
        // Minimal schema mirroring the real table: [FILL IN]
        $this->pdo->exec('CREATE TABLE orders (customer_id INT, total REAL, created_at TEXT)');
    }

    public function test_given_customer_without_orders_when_total_is_100_then_current_result(): void
    {
        $now = new DateTimeImmutable('2025-03-15 10:00:00');

        $result = calculateDiscount(['id' => 42], 100.0, $this->pdo, $now);

        $this->assertSame(0.0, $result); // [FILL IN: run and paste the real output]
    }

    public function test_given_negative_total_then_it_does_not_throw(): void
    {
        // POSSIBLE BUG: a negative total is not rejected; we lock in current behavior
        $result = calculateDiscount(['id' => 42], -50.0, $this->pdo, new DateTimeImmutable());
        $this->assertIsFloat($result);
    }
}

Run each test first, paste the real value into the assertion, and only then start refactoring…

Key facts

Category
Programming & development · Refactoring
Output type
Code
Level
Intermediate
Designed for
ChatGPT, Claude, Gemini and Microsoft Copilot
Verified in
Pending editorial verification
Variables
Language and test framework, Hard dependencies, Goal afterwards and Code
Language
English
Price
Free, no sign-up
Updated
Nov 7, 2026

Frequently asked questions

What is a characterization test?

A test that documents what the code does today, not what it should do. It acts as a safety net: if a refactor changes a result, the test tells you.

What if the code has an obvious bug?

Lock it in first with a test flagged as a possible bug and finish the safety net. Fix it later in a separate change so you do not mix refactoring with behavior changes.

What is this prompt for?

Create characterization tests for untested legacy code: lock in current behavior, isolate dependencies like the database or clock and plan a safe step-by-step refactor.

Which AI tools does it work with?

It is designed for ChatGPT, Claude, Gemini and Microsoft Copilot. We have not verified it in these tools yet, so results may vary between them.

How do I customize the prompt?

Click “Customize” and fill in the variables (Language and test framework, Hard dependencies, Goal afterwards and Code). The text updates instantly and you can then copy it in one click. Values are stored only in your browser.

Do I need experience to use it?

It is intermediate: it helps to know the topic so you can provide good context and review the result critically.

Is this prompt free?

Yes. Every HomeCasa Prompts prompt is free, with no sign-up or subscription. You can also use them in professional projects.

Can I trust the AI output?

Treat it as a high-quality draft: always check data, figures and important claims before publishing or making decisions.

Related prompts