Augmented Unit Test Generation Using LLMs

adyen · Finance · 2024 · source Agentic: no · promotional bias: low · source-backed · extracted with prompt 0.5.4 (schema v2)

Generated from extraction.json — do not edit by hand. Every claim cites verbatim source evidence; stated means the quote directly asserts the claim, implied means it supports it indirectly.

Problem

Domain: Unit test generation

Adyen explored whether LLMs could help developers generate unit tests for large production codebases, where useful tests require the right surrounding code context rather than generic text generation.

Constraints:

Architecture

Adyen’s approach frames LLM unit-test generation as a context-selection problem. A code-context retrieval layer identifies relevant snippets around the method under test, including dependencies and invisible logic behind abstractions, and feeds those snippets to an LLM so it can propose tests that complement existing code. The article contrasts this with ordinary RAG over text and with fine-tuning: RAG can retrieve relevant information, but code requires richer structural context; fine-tuning can help specialized generation but is expensive and hard to refresh in fast-moving codebases.

Diagram confidence: reconstructed (reconstructed from prose).

flowchart LR
  developer["developer"] --> unit-test-generation-workflow["unit-test-generation-workflow"]
  unit-test-generation-workflow["unit-test-generation-workflow"] --> codebase-context-retriever["codebase-context-retriever"]
  large-existing-codebase["large-existing-codebase"] --> codebase-context-retriever["codebase-context-retriever"]
  codebase-context-retriever["codebase-context-retriever"] --> test-generation-llm["test-generation-llm"]
  test-generation-llm["test-generation-llm"] --> unit-test-generation-workflow["unit-test-generation-workflow"]
  unit-test-generation-workflow["unit-test-generation-workflow"] --> test-suite["test-suite"]
  test-suite["test-suite"] --> developer["developer"]
Drag to pan · scroll or use +/− to zoom · reconstructed from the source's described component topology

Components

Component Role Interacts with
developer Engineer who identifies code needing tests and reviews LLM-generated candidates. unit-test-generation-workflow
unit-test-generation-workflow Workflow that coordinates code selection, context retrieval, LLM generation, and developer review. developer, codebase-context-retriever, test-generation-llm, test-suite
large-existing-codebase Production code framework whose dependencies and abstractions must be understood before writing tests. codebase-context-retriever
codebase-context-retriever Finds relevant snippets, dependencies, abstract implementations, and system interactions for the method under test. large-existing-codebase, unit-test-generation-workflow, test-generation-llm
test-generation-llm LLM that uses retrieved code context to propose unit tests. codebase-context-retriever, unit-test-generation-workflow
test-suite Human-reviewed tests that complement and verify the existing code. unit-test-generation-workflow, developer

Data flow

A developer or tool selects code that needs unit tests. The context-retrieval step finds the relevant class/method sections, dependencies, interactions, and implementation details needed to understand the method’s role. Those snippets are provided to the LLM, which generates candidate unit tests that implement assertions around existing behavior. Developers review and integrate the generated tests into the normal code-quality workflow.

4 supporting quotes
“This article will show how to spot and provide the relevant code snippets to the LLM.”article, stated
“To optimize their performance, it's essential to guide LLMs in comprehending the entire codebase architecture.”article, stated
“sending the correct code snippets allows the LLM to truly understand the code and assist the engineer in generating unit tests.”article, stated
“Implement the necessary unit tests that complement and verify the functionality of the existing code.”article, stated

Why this architecture

The article argues that unit-test generation cannot be treated like ordinary text RAG because code behavior depends on relationships across methods, abstractions, and dependencies. The architecture therefore emphasizes finding the right code snippets before generation. Fine-tuning is acknowledged as useful for specialized behavior, but codebases change daily, making retrieval and per-task context selection more practical for developer assistance.

4 supporting quotes
“This isn't necessarily the case for code. The actual implementation is often done using an abstract method; thus, it's necessary to adequately capture and feed these relevant code segments to the LLM, allowing them to understand the 'invisible' logic in the code.”article, stated
“creating a unit test demands a comprehensive understanding of the method within the broader system’s operations.”article, stated
“codebases frequently update daily.”article, stated
“every challenge presented to the LLMs is different and thus requires a specialized approach.”article, stated

Models used: LLMs · GitHub Copilot · RAG · vector embeddings · fine-tuning

Scale

Alternatives considered (roads not taken)

Conventional text RAG over a knowledge base

Rejected because: Text-style retrieval does not automatically capture code dependencies, abstractions, and interrelated behavior needed for unit tests.

“The conventional RAG (Retrieval Augmented Generation) architecture adeptly handles text generation tasks”article, stated
“This isn't necessarily the case for code. The actual implementation is often done using an abstract method; thus, it's necessary to adequately capture and feed these relevant code segments to the LLM, allowing them to understand the 'invisible' logic in the code.”article, stated

Fine-tune a model for the codebase

Rejected because: Fine-tuning can help specialized domains but is resource-intensive and hard to keep current with daily code changes.

“challenges arise due to the resource-intensive nature of fine-tuning and its inability to keep up with the rapid evolution common in software development environments, where codebases frequently update daily.”article, stated
“its inability to keep up with the rapid evolution common in software development environments”article, stated

Ask the LLM to generate tests without targeted code snippets

Rejected because: The article says correct snippets are necessary for the LLM to understand invisible code logic and assist test generation.

“it's necessary to adequately capture and feed these relevant code segments to the LLM”article, stated

Patterns

rag-retrieval (context)

The system retrieves code snippets relevant to the unit under test before asking the LLM to generate tests.

“spot and retrieve contextually relevant information from the information retrieval layer.”article, stated

context-compaction (context-management)

Rather than sending an entire codebase, the workflow selects the snippets needed for the LLM to understand the code under test.

“sending the correct code snippets allows the LLM to truly understand the code”article, stated

fine-tuning-adaptation (model-adaptation)

Fine-tuning is discussed as an option for specialized contexts, but not the default for fast-changing code.

“Fine-tuning offers more significant benefits in other cases, especially those requiring more exact or nuanced content generation.”article, stated

human-in-the-loop-gate (developer-workflow)

The LLM assists engineers in generating tests; the framing is augmented developer assistance rather than autonomous test acceptance.

“assist the engineer in generating unit tests.”article, stated

Tradeoffs

Use retrieval/context selection for code understanding

Chose task-specific code snippets over blind generation from the target method alone.

Rationale: Relevant snippets help the LLM reason about dependencies and hidden logic before generating tests.

“it's necessary to adequately capture and feed these relevant code segments to the LLM”article, stated

Keep humans in the test-generation loop

Chose augmented unit test generation over fully automated test authoring and acceptance.

Rationale: The article frames LLMs as assistants that help engineers generate tests, preserving developer responsibility for correctness.

“assist the engineer in generating unit tests.”article, stated

Gotchas (what bit them)

Code context is structurally different from prose context.

Root cause: A method’s test behavior depends on dependencies, abstract implementations, and interactions with the wider system.

Resolution: Retrieve and feed the relevant code segments that expose the method’s role and invisible logic.

“one must understand the method's role – its dependencies and how it interacts with other system parts.”article, stated
“allowing them to understand the 'invisible' logic in the code.”article, stated

A single LLM integration strategy does not fit every development task.

Root cause: Some tasks need up-to-date retrieval, while others need exact specialized generation.

Resolution: Select among RAG, fine-tuning, or specialized approaches based on the task’s requirements.

“every challenge presented to the LLMs is different and thus requires a specialized approach.”article, stated
“In some cases, RAG pipelines are ideal”article, stated

Evaluation

The article is exploratory and does not report a formal benchmark. Its evaluation lens is whether selected snippets let the LLM understand code enough to generate unit tests that complement and verify existing behavior.

Metrics: relevance of retrieved code snippets · developer usefulness · unit tests generated · coverage/complementarity to existing code · fit to fast-changing codebase

“Spot sections of the code that are relevant when writing unit tests.”article, stated
“Implement the necessary unit tests that complement and verify the functionality of the existing code.”article, stated

Outcomes

The source does not report deployment counts or measured productivity gains. It grounds scale in large pre-existing frameworks and codebases that update daily.

“Integrating Large Language Models (LLMs) into today's applications demands a deep understanding of the technology and its specific application needs.”article, stated
“From our experience, sending the correct code snippets allows the LLM to truly understand the code”article, stated