Apply to my task
arXiv:2604.19826 ★ 80 Apr 20, 2026

Co-Located Tests: Placing Examples Next to the Code in the Prompt Sharply Improves Generation Quality

Key result

Identical examples, one request — but accuracy jumps from 0% to 100% depending on where the examples sit in the prompt. The co-located tests method lets you get correct code on the first try — no iterations, no fixes. The trick: examples inside the docstring sit a line away from the function — the transformer processes them as a single whole. Move the tests to the end of the prompt and the link between the example and the task weakens by 2.8–4.4 times, and the model starts guessing the behavior instead of following the examples.

01

TL;DR

If the examples of how the code should behave are written right next to the function in the prompt — inside its description — the AI generates significantly better code than when the same examples are moved to a separate block at the bottom. It's counterintuitive, but the difference is huge: some models completely ignore the examples when they're "separate tests," while others produce nearly perfect results when they're "inline."

LLMs have a weakness: the farther an example is from where the task is described in the prompt text, the weaker the link between them in the model's processing. A prompt with tests at the bottom is like a spec with the examples at the end of the document: the developer keeps flipping back and forth. For the AI this literally means weakened "attention" — the examples and the task are linked 2.8–4.4 times more weakly than with inline placement.

Embed the examples right in the function description — via >>> in the docstring or via a comment nearby — and the AI perceives the task and the expected behavior as a single whole. The result: 92–100% correct answers versus a spread of 0–100% with separate tests.

Want this for your own case? Apply this study to your task: AI adapts its method to what you are working on and writes the prompt.

02

Method Blueprint

❌ Ordinary prompt (sep):
  def function(params): → description
  ...code or an empty stub...
  # TESTS AT THE BOTTOM:
  assert function(2) == 4

✅ Inline prompt (co-located):
  def function(params):
      """What it does
      >>> function(2)
      4
      >>> function(0)
      0
      """
      pass  ← the AI writes the implementation

Both variants — one prompt, one request.
The only difference is where the examples go.
03

Example in Action

Task: You're setting up a simple Discord bot for your store. You ask the AI to write a function that formats a price from a number into nice text for a message.

❌ Prompt without co-location (the usual way people write it):

Write a format_price function in Python that takes a number 
and returns a string with the price in dollars.

The function should:
- Add the dollar sign
- Use a comma as the thousands separator
- If 0 — write "Free"

Tests:
assert format_price(1500) == "$1,500"
assert format_price(0) == "Free"
assert format_price(1000000) == "$1,000,000"

✅ Prompt with co-location:

def format_price(amount: int) -> str:
    """Formats a price for a message in a store's Discord bot.

    >>> format_price(1500)
    '$1,500'
    >>> format_price(0)
    'Free'
    >>> format_price(1000000)
    '$1,000,000'
    >>> format_price(99)
    '$99'
    """
    pass

Write the implementation of the function.

Result: In the second variant, the model sees the examples right inside the function description — they're physically next to def format_price. The model is highly likely to keep all the examples intact and write a correct implementation. In the first variant, the model may rewrite the tests, ignore the zero edge case, or write code that doesn't pass all the checks.

04

Why It Works

The LLM's weakness: A transformer (the architecture of most models) processes text as a sequence, and the strength of the link between two parts of the text decays with distance. Tests at the end of the prompt are instructions the model "sees" hundreds of tokens after the function description. The link is blurred.

The LLM's strength: The model is very good at picking up local context — whatever is written nearby gets processed together. When >>> format_price(1500) sits a line after def format_price, the model literally processes them as a unit.

How the method uses this: The >>> markers inside the docstring create structural proximity between the example and the function in the token stream. The researchers measured it: in 5 of 7 architectures, attention from the >>> marker to the function tokens is 2.8–4.4 times stronger than from #[test] in a separate block. This works not only in transformers — they checked it on an RNN architecture, and the effect was even stronger.

Control knobs: - Number of examples → more >>> lines = more constraints on the model, less room for interpretation - Edge cases nearby → add >>> function(0), >>> function(-1) right in the docstring — you'll cover the extreme situations - A comment after >>> → >>> function(None) # should return an error sets the behavior on errors

05

Prompt Template

def {function_name}({params}):
    """{One line: what the function does}

    >>> {function_name}({typical_input_1})
    {expected_result_1}
    >>> {function_name}({typical_input_2})
    {expected_result_2}
    >>> {function_name}({edge_case})
    {edge_case_result}
    """
    pass

{Additional requirements if any}
Write the implementation.

What to fill in: - {function_name} — a clear name: calculate_discount, parse_phone, format_date - {params} — what it takes: price, percent or phone_number - {typical_input} — the ordinary working case - {edge_case} — zero, empty string, None, a very large number - {expected_result} — exactly what the function should return (including quotes for strings)

How many examples to give: 3–5 is optimal. Fewer than two — the model guesses the pattern. More than seven — overkill.


🚀 Quick start — paste into the chat:

Here's a template for writing code with inline tests. 
Adapt it to my task: {your task}.
Ask me questions to fill in the fields.

[paste the template above]

The LLM will ask what the function does, what parameters it takes, and which edge cases matter — because without that it can't fill in the >>> examples correctly. It will take the template's structure and plug in your data.

06

Limitations

⚠️ It depends on the model: Some models ignore this principle — Code-LLaMA showed the opposite effect (it worked better with separate tests). There's no universal rule, but for most top models co-location works.

⚠️ Not for complex logic without examples: If you don't know what the function should return in edge cases, it's better to ask the model first, then rephrase with inline examples.

⚠️ Behavior changes with updates: Claude 3.5 Haiku lost the ability to preserve inline tests that Haiku 3 had. Then it got it back in 4.5. What worked yesterday may not work after a model update.

⚠️ Python-specific: The >>> syntax is Python doctest. For other languages you need to adapt the format (comments next to the function). The principle is the same: proximity of the example to the code.

07

How They Studied It

The researcher took one non-trivial task — implementing a d-ary heap (a data structure used in routing algorithms) — and asked 12 models from three providers to write it 50 times each. He compared two formats: Python with >>> inside the docstring and Rust with #[test] in a separate block.

An unexpected finding: the more powerful models (Opus 4, 4.1, 4.5) completely ignored the tests in the separate block, while the less powerful Haiku 4.5 preserved them and ran them at 100%. This is direct proof that the problem isn't the complexity of the language but the structure of the tests — after all, Opus can write Rust, it simply "decided" that the tests were a specification rather than content to preserve.

The mechanics were confirmed by measuring attention in 7 open models (including one RNN architecture). They checked it causally: when they "turned off" the links between the test marker and the function tokens, quality dropped. The fact that the effect works in an RNN too (which doesn't use an attention mechanism like a transformer) points to a fundamental property of sequential processing, not an artifact of a specific architecture.

08

Straight From the Research

def heap_insert(heap: list, item: Any, d: int) -> None:
    """Insert item into d-ary heap.

    >>> h = []
    >>> heap_insert(h, 5, 3)
    >>> heap_insert(h, 3, 3)
    >>> heap_insert(h, 7, 3)
    >>> h[0]
    3
    >>> heap_insert(h, 1, 3)
    >>> h[0]
    1
    """
    pass

Context: This is the prompt format from the "Directives" experiment — where the researchers gave the models functions with prompt-provided doctests. The models had to write the implementation while keeping all the >>> examples intact.

09

Adaptations and Extrapolations

💡 Adaptation: the principle works beyond Python

The >>> syntax is specific to Python. But the proximity principle is universal. For any language, or even for describing an API, embed the examples right in the function's context:

Write a JavaScript function to calculate a discount:

// Usage example:
// calculateDiscount(1000, 10) → 900
// calculateDiscount(500, 50) → 250  
// calculateDiscount(0, 10) → 0
function calculateDiscount(price, percent) {
  // implementation
}

🔧 Technique: add an explanation to the example → the model understands the intent

By default, >>> just shows input-output. Add a comment — and the model understands why the result is what it is:

>>> format_price(1000000)
'$1,000,000'  # comma as the thousands separator, for the US format
>>> format_price(0)
'Free'        # zero is a special case, not "$0"

This reduces the chance that the model does it "right" its own way, but not yours.


🔧 Technique: monitoring after a model update

The study showed: models change behavior with updates. Haiku 3 → 3.5 → loss of test preservation. Opus 4/4.1/4.5 ignore tests → Opus 4.6 restored it.

A simple check for your working prompts after a model update:

Check: will you keep all the examples from the docstring in your answer, 
and should your code pass them?

def test_func(x):
    """
    >>> test_func(2)
    4
    >>> test_func(0)
    0
    """
    pass

If the model removed the >>> lines or changed the expected values, that's a regression — the prompt needs adapting.

10

Resources

Paper: Co-Located Tests, Better AI Code: How Test Syntax Structure Affects Foundation Model Code Generation
Accepted at AIware 2026, Montreal
Preprint: arXiv (long version with appendices A and B)

Author: Éric Jacopin (Cosmic AI) — [email protected]

Tools mentioned: GitHub Copilot, Claude Code, Cursor, Augment Code, Kiro
Benchmarks in context: SWE-bench, HumanEval, MBPP, LiveCodeBench
Models in the study: Claude (Haiku 3/3.5/4.5, Sonnet 4/4.5, Opus 4/4.1/4.5/4.6), Mistral Medium, Devstral-2512, EssentialAI RNJ-1
Open-source architectures for the MI analysis: Qwen2.5-Coder-7B/3B, StarCoder2-3B, CodeGemma-7B, Code-LLaMA-7B, Phi-3-mini, RWKV-6-Finch-1B6

Research digest

Key result

Identical examples, one request — but accuracy jumps from 0% to 100% depending on where the examples sit in the prompt. The co-located tests method lets you get correct code on the first try — no iterations, no fixes. The trick: examples inside the docstring sit a line away from the function — the transformer processes them as a single whole. Move the tests to the end of the prompt and the link between the example and the task weakens by 2.8–4.4 times, and the model starts guessing the behavior instead of following the examples.

Principle

A transformer isn't an editor that reads the whole text. It's a mechanism that, for each token, asks: "where should I look right now?" The farther the example is from the function, the less often the model looks at it during generation. The `>>>` format inside the docstring places the example a couple of tokens from the function description — the model literally can't ignore it. Tests at the bottom of the prompt are like a spec with the examples at the end of a forty-page document: it's all written down, but the link is blurred.

Why it works

The researchers measured the strength of the transformer's attention from the example marker to the function tokens. In 5 of 7 architectures, a `>>>` marker inside the docstring gives a link 2.8–4.4 times stronger than a separate test at the bottom. A strong link means the model knows what it's writing the code for, rather than just filling in an empty function. The effect reproduced even on RNN architectures — which means it's not just about transformers. Proximity = understanding. It works at the level of the architecture, not the training.

When to apply

Writing code via an LLM — especially for functions with clear logic: formatting, calculations, parsing, data processing. Especially useful when the task seems simple but has edge cases — zero, empty string, a negative number. NOT suitable for architectural questions like "how to organize a project" — there's nothing to put in `>>>`. NOT suitable if you yourself don't know the expected result: without concrete examples, a doctest won't help.

Mini recipe

1. Start with the function, not the assignment: the first line of the prompt is `def function_name(params):`, not 'write a function that...' 2. Add a docstring with examples: right under `def`, open triple quotes, write one line about what it does — and immediately `>>> name(typical_input)` with the result on the next line 3. Cover edge cases right there: add `>>> name(0)`, `>>> name('')`, `>>> name(None)` — all inside the docstring, not as a separate list 4. Close with a stub: after the closing quotes — `pass` or `...` 5. One line at the end: `Write the implementation.` — and that's it

Examples

[BAD]: `Write a parse_phone(phone) function that normalizes a phone number to the format +1XXXXXXXXXX. Tests: assert parse_phone('5551234567') == '+15551234567', assert parse_phone('+15551234567') == '+15551234567'` [GOOD]: `def parse_phone(phone: str) -> str: """Normalizes a phone number to the format +1XXXXXXXXXX. >>> parse_phone('5551234567') '+15551234567' >>> parse_phone('+15551234567') '+15551234567' >>> parse_phone('(555) 123-45-67') '+15551234567' >>> parse_phone('') '' """ pass Write the implementation.`

In plain words

The gist is that today's models aren't programmers with systems thinking — they're statistical predictors that are wildly dependent on the distance between words. If you give the task at the start of the text and dump the examples of how it should work way down at the bottom, the model simply "loses focus." To it, those are two separate chunks of data, and the link between them is hanging by a thread. To get the AI to produce decent code, you need to use co-location — cramming the tests and examples right into the function's description, literally in the adjacent lines.

It's like giving directions to a cab driver: first you name the address, and ten minutes into the ride you add that you need to cut through the back streets. Technically you said everything, but the driver already blew past the turn and is following the GPS. Same story with code: when the tests sit at the end, the model starts writing the implementation based only on the general description, and by the time it "gets to" the specific conditions, the code is already hopelessly botched with the wrong logic.

In practice, the difference between the methods is enormous. The ordinary sep approach (tests separate) makes models fumble and ignore edge cases. But the moment you switch to the inline format, where the examples sit right inside the docstring via >>>, the magic kicks in. For instance, if you ask for a price-formatting function, don't write the tests at the bottom of the file. Put them right in the function's "header": "if the input is 500, the output should be $500.00." That way the model sees the goal and the means in one attention window, and generation accuracy shoots up, because the context distance shrinks to zero.

This principle is universal and reaches far beyond writing Python scripts. It was tested on code, but it works anywhere there's a complex instruction: in prompts for legal documents, in configuring chatbots, or in building content plans. If you want the AI to account for a specific nuance, write it right up against the object, not in a list of footnotes at the end of the message. SEO for an AI's brain isn't about keywords — it's about how close you placed the instruction to the executor.

Bottom line: stop bloating your prompts and hoping the model will "connect" the beginning with the end on its own. Use structural proximity, sew the examples into the description, and don't give the transformer a chance to forget what you want from it. Either you pack the data tightly, or you get crippled code on the output that fails on the very first check. Whoever learns to group meanings will get results on the first try, while everyone else burns tokens on endless revisions.

AI lab assistant

Apply this study to your task

Describe what you're working on. AI takes the method and the measured results from this paper and adapts them to your case, or writes a ready prompt built on them.

Based on Co-Located Tests: Placing Examples Next to the Code in the Prompt Sharply Improves Generation Quality arXiv:2604.19826

Sign in to apply this study New accounts get 50 free credits.