Papers
Topics
Authors
Recent
Search
2000 character limit reached

Grounding AI Agents in Contracts: An Empirical Evaluation of Spec-Driven Test Generation

Published 17 Aug 2026 in cs.SE | (2608.17177v1)

Abstract: LLM-based agents are increasingly used for coding tasks, where they have outperformed many classical approaches and scaled to repository-level tasks, such as test generation. However, when directly prompted to generate tests, these agents can fail to reason about the code and its underlying contracts, thereby missing edge cases and behavioral boundaries that affect test quality. To address this limitation, we propose Spec-Driven Test Generation, where we instruct an agent to first reason about -- and explicitly document -- code pre-conditions, post-conditions, and undefined behaviors. This intermediate semi-formal specification acts as a cognitive scaffold to guide subsequent test generation. Our evaluation on production bugs from Google shows that the spec-driven agent can deliver a 9.8 percentage points (p=0.0352p = 0.0352) improvement in bug detection rate and a 2.5 percentage point (p=0.0034p = 0.0034) improvement in branch coverage, compared to a traditional test generation agent baseline. Using LLM-as-a-Judge, we further show that test suites generated by the spec-driven agent are superior to the baseline and human-authored tests in 77.8% and 56.7% of the cases, respectively, and demonstrated improvements on following best practices, readability, and edge-case coverage.

Summary

  • The paper introduces a two-phase workflow that first infers semi-formal contracts and then uses them to guide unit-test generation, improving five-run bug detection from 53.4% to 63.2% across 90 Google production bugs.
  • The spec-driven agent increased branch coverage from 46.4% to 48.9% and produced stronger edge-case tests, while maintaining nearly identical test pass rates and leaving mean line coverage essentially unchanged.
  • The approach’s effectiveness depends on recovering the violated contract—raising conditional detection from 19.4% to 54.9%—but it required 38% more tokens, highlighting a quality-versus-cost trade-off.

The paper presents Spec-Driven Test Generation, a two-phase agentic workflow intended to improve the semantic effectiveness of LLM-generated unit tests. Its central claim is that direct test synthesis leaves the agent without an explicit behavioral oracle, encouraging superficial path exploration, missed boundary conditions, and weak assertions. The proposed solution is to require the agent to first infer and document a semi-formal contract for the target code, then use that artifact to guide test construction. Evaluated on 90 historical production bugs from Google, the approach improves fault detection and branch coverage relative to an otherwise identical direct-generation baseline, while incurring a substantial token overhead (2608.17177).

Problem formulation and conceptual basis

The work adapts Design by Contract to repository-level agentic test generation. Traditional contracts are typically written by developers before or alongside implementation, whereas the setting considered here involves existing code whose intended behavior is only partially explicit. The agent therefore performs retroactive contract inference using source code, documentation, comments, existing usage patterns, and other repository context. The objective is not formal verification or proof of functional correctness. Rather, the specification is a structured natural-language artifact that provides a defect-oriented testing oracle.

For each code unit, the specification contains four elements: a behavioral description, preconditions, postconditions, and local test suggestions. Conditions are additionally marked as either already tested or untested. An untested condition is intended to yield a concrete test obligation. This representation combines the reviewability and expressive flexibility of natural language with the organizational discipline of contract-based reasoning. It is consequently less rigorous than Hoare logic, JML, Dafny, or SMT-based specifications, but more directly usable in heterogeneous, multilingual codebases.

The approach also differs from dynamic invariant miners such as Daikon. Dynamic miners treat observed executions as evidence of intended behavior, which can encode faulty behavior as an invariant. The proposed agent instead attempts to infer developer intent from multiple semantic sources. That distinction is important in a historical-bug setting: the target is not merely to summarize what the buggy or fixed implementation does, but to identify the behavioral constraint that the defect violates.

Spec-driven generation framework

The framework separates specification extraction from test synthesis. In Phase I, the agent aggregates contextual information, infers behavioral boundaries, compares inferred conditions with available tests, and produces suggestions for uncovered conditions. The paper does not programmatically enforce that every API or condition is represented; completeness is encouraged through prompting and agent behavior. The artifact can optionally be reviewed and amended by a developer before synthesis, although the empirical evaluation deliberately omits this human-in-the-loop stage.

Figure 1

Figure 1: Overview of spec-driven test generation.

In Phase II, the specification and its test suggestions are supplied to the same agent architecture used for the baseline. The agent implements the suggestions, modifies only the permitted test and build files, executes the tests, and iterates based on compilation or runtime feedback. The specification therefore functions both as a planning document and as an oracle-oriented context scaffold. Its intended effect is not simply to increase the volume of generated tests, but to focus generation on input constraints, error behavior, state transitions, side effects, and branch boundaries.

The experimental comparison isolates this intermediate reasoning step. Both configurations use Gemini 3 Flash, identical inference parameters, the same repository-navigation tools, and the same agentic harness. The baseline receives source code and is directly instructed to produce a comprehensive test suite. The spec-driven agent must first generate the contract artifact and then synthesize tests from it. This control is methodologically valuable because it reduces the likelihood that differences arise from model choice, tool access, or execution infrastructure.

Industrial evaluation protocol

The evaluation uses 90 reproducible, human-filed production bugs from Google’s internal issue-tracking system. Each bug is represented by a buggy implementation and its corresponding fixed implementation. The dataset spans C++, Java, Python, and Go, but is restricted to fixes affecting a single production source file, with a corresponding test file and optional build configuration changes. This restriction makes fail-to-pass evaluation tractable, although it limits the scope of the conclusions for multi-file defects and broader integration failures.

The study adopts a greenfield setup. Existing tests are removed before agent execution, and the agent is given the fixed source without access to the issue description, commit message, or fix diff. Generated tests must compile and pass on the fixed implementation. The workspace is then reverse-patched to the buggy version, and a bug is counted as detected if at least one generated test fails. Build failures do not count as detections. Post-execution audits discard runs in which the agent modifies the source under test or unrelated pre-existing files.

The primary quantitative measure is detect@k, where kk independent stochastic generations are attempted for each bug. The paper reports results for kk from 1 through 5, using bug-level bootstrap confidence intervals and McNemar’s test for paired detection outcomes. Structural coverage is measured using line and branch coverage on the fixed implementation, with paired comparisons evaluated using the Wilcoxon signed-rank test. Qualitative test quality is assessed by Gemini 3.1 Pro, which compares anonymized suites across best-practice adherence, readability, edge-case coverage, and overall superiority. Five judge invocations are aggregated by majority vote.

Fault detection and structural coverage

Both agents produce valid test suites at nearly identical rates. At one attempt, pass@1 is 94.4% for the baseline and 94.2% for the spec-driven agent; at five attempts, both reach 98.9%. This result is important because it rules out a simple explanation in which the proposed method improves bug detection merely by producing more compilable tests. The difference is semantic rather than syntactic.

Metric Baseline Spec-driven Difference Significance
detect@1 36.9% 41.1% +4.2 pp p=0.3075p = 0.3075
detect@3 49.4% 56.6% +7.2 pp p=0.0574p = 0.0574
detect@5 53.4% 63.2% +9.8 pp p=0.0352p = 0.0352
Line coverage 74.8% 74.4% -0.4 pp p=0.3659p = 0.3659
Branch coverage 46.4% 48.9% +2.5 pp p=0.0034p = 0.0034

The spec-driven agent outperforms the baseline at every execution budget. At k=5k=5, it detects 63.2% of historical bugs compared with 53.4% for the baseline, an absolute improvement of 9.8 percentage points that is statistically significant under McNemar’s test. The performance gap increases with additional samples: from 4.2 points at k=1k=1 to 9.8 points at k=5k=5. The implication is that independent sampling is more productive when each generation is constrained by an explicit behavioral scaffold, although the study does not establish whether the improvement results from greater diversity, better prioritization, or both.

The overlap analysis further supports a meaningful qualitative difference. The two agents detect 45 bugs in common; the spec-driven agent uniquely detects 12 bugs missed by the baseline, whereas the baseline uniquely detects only 3 bugs missed by the spec-driven agent. Thus, the improvement is not attributable solely to a uniform increase in detection probability. The intermediate contract appears to expose some defect classes that direct prompting systematically overlooks.

The coverage results are more selective than the detection results. Mean line coverage is essentially unchanged, with a nonsignificant decrease from 74.8% to 74.4%. Branch coverage, however, increases from 46.4% to 48.9%, and the 2.5-point difference is statistically significant. This divergence is technically consequential: line coverage can be increased by exercising straight-line code without testing alternative outcomes, whereas branch coverage more directly reflects exploration of conditional behavior, exception paths, and boundary decisions. The result supports the paper’s claim that the specification encourages deeper control-flow exploration rather than merely increasing execution volume.

The data also reveal substantial per-bug heterogeneity. At kk0, 65.6% of baseline bugs fall at either 0% or 100% detection across runs, compared with 57.8% for the spec-driven agent. The proposed method shifts some bugs from complete nondetection into an intermediate regime in which detection is conditional. This reduces, but does not eliminate, the strongly bimodal difficulty distribution. Consequently, the reported confidence intervals remain wide, and the aggregate mean should not be interpreted as uniform effectiveness across defects.

Qualitative rigor of generated tests

The qualitative evaluation compares 83 successfully generated spec-driven suites with baseline suites and with the original developer-written suites. The judge exhibits at least 90% self-agreement across criteria and a tie rate no greater than 5.6%, although these reliability measures concern consistency of the evaluator rather than agreement with human experts.

Figure 2

Figure 2: Pairwise LLM-as-a-Judge comparison of baseline-generated and spec-driven test suites.

Against the baseline, the spec-driven suites are judged overall superior in 77.8% of cases. They are preferred for testing best practices in 65.6% of cases, readability in 68.9%, and edge-case coverage in 83.3%. The strongest result is therefore not general stylistic preference but boundary-oriented behavior. The judge identifies more explicit validation of exceptional inputs, missing optional fields, boundary values, and negative paths. It also reports more localized assertions, stronger naming conventions, and more idiomatic use of test-framework facilities.

These qualitative outcomes are consistent with the branch-coverage and fault-detection results. A contract organized around preconditions and postconditions naturally directs the agent toward behaviorally distinct states rather than only method invocation. Nevertheless, the LLM-as-a-Judge design introduces construct-validity concerns. The evaluator may favor verbosity, stylistic regularity, or outputs resembling its own training distribution. The paper mitigates this with anonymization, randomized ordering, a stronger judging model, and repeated voting, but does not provide human adjudication or inter-rater comparison.

Figure 3

Figure 3: Pairwise comparison between developer-written suites and spec-driven suites, showing competitive qualitative quality.

Compared with developer-authored tests, the spec-driven suites are rated overall superior in 56.7% of cases, which the paper interprets as approximate parity with human engineering rigor. The agent’s strengths include narrow assertions, reduced boilerplate, explicit negative-path testing, and robust concurrency constructs such as absl::Notification. Human-written suites remain stronger on intricate algorithmic scenarios, complex state transitions, and timezone-sensitive behavior. The agent also occasionally violates public API encapsulation through reflection-based access to private methods. The comparison therefore does not establish general superiority over human testing; it indicates that, under this evaluation protocol, contract-guided generation can produce suites competitive with developer-authored artifacts on several observable quality dimensions.

Contract coverage as an explanatory metric

The paper introduces ContractCoverage@k to separate specification quality from downstream test-generation quality. The metric asks whether the generated specification explicitly captures the behavioral contract violated by the historical bug. It is deliberately defect-oriented rather than a measure of complete semantic coverage. A specification can therefore receive positive Contract Coverage while omitting many valid behaviors unrelated to the selected defect.

ContractCoverage@1 is 61.1%, increasing to 69.7% at kk1 and 78.9% at kk2. More importantly, contract coverage strongly predicts fault detection. When the specification captures the violated contract, the resulting suite detects the bug in 54.9% of runs, compared with 19.4% when the contract is absent. Fisher’s exact test yields kk3, with a moderate Phi association of kk4.

This conditional analysis clarifies the mechanism behind the aggregate improvement. Specification generation is not merely an extra textual planning step: successful contract recovery substantially increases the probability that synthesis will produce a fault-revealing test. However, the 54.9% conditional detection rate also shows that a correct specification is insufficient. In 110 runs, the agent identified the relevant contract but still failed to detect the bug. Failures include inadequate input data, omitted scenarios, weak assertions, flawed test logic, and invalid test code. Conversely, 34 runs detect bugs without Contract Coverage, likely through generic structural execution or broad crash assertions. The specification is therefore a useful but imperfect oracle.

The paper categorizes specification-generation failures into omitted methods, missing error handling, omitted data transformations, abstraction of constants, and missing execution constraints. These categories identify a central bottleneck: the agent may produce a coherent-looking contract while omitting exactly the low-level value mapping, ordering constraint, or exceptional behavior that distinguishes correct from incorrect execution. The artifact’s semi-formal nature improves accessibility but does not provide machine-checkable guarantees against omission or hallucination.

Cost and efficiency trade-offs

The method requires materially more inference. Across five runs of the 90-bug dataset, the baseline consumes 243.9 million tokens, whereas the spec-driven configuration consumes 336.7 million, a 38.0% increase. Input consumption rises by 36.2%, primarily because specifications are added to the synthesis context, while output consumption rises by 59.1%, reflecting both specification generation and larger test suites.

The spec-driven agent detects 57 unique bugs compared with 48 for the baseline, an 18.8% increase in unique bugs. However, tokens per unique bug detected increase from 5.1 million to 5.9 million, or 16.2%. The approach therefore improves absolute yield but not token-normalized efficiency. This distinction matters for deployment decisions: the method is advantageous when additional inference cost is acceptable and fault-finding quality is prioritized, but the evidence does not support the claim that specification grounding is computationally cheaper.

Limitations and open questions

The empirical scope is limited to 90 bugs from one organization and to defects whose fixes modify a single production file. Google’s monorepo, internal conventions, documentation density, build infrastructure, and testing practices may differ substantially from open-source repositories or other industrial environments. The study also evaluates only Gemini 3 Flash as the generation model and Gemini 3.1 Pro as the judge. Absolute rates may change with model family, prompting strategy, context-window behavior, or tool implementation.

The greenfield protocol provides experimental control but removes existing tests that would normally supply naming conventions, fixtures, behavioral examples, and implicit contracts. Results therefore characterize specification-guided generation under deliberately sparse evidence, not necessarily incremental augmentation of a mature test suite. Similarly, historical bug detection measures regression-test recovery rather than discovery of previously unknown defects.

The LLM-as-a-Judge is the principal threat to qualitative and specification-validity claims. Repeated majority voting improves consistency but cannot establish semantic correctness. ContractCoverage itself depends on a known fix and evaluates only the contract relevant to that fix. It does not penalize over-specification, contradictory conditions, hallucinated requirements, or omissions outside the selected defect. The paper also does not include an ablation separating the effects of structured contract extraction from simpler planning artifacts such as pseudocode, explicit test plans, execution traces, or chain-of-thought-like decomposition. Finally, the optional HITL stage is not evaluated, leaving open whether expert curation improves detection enough to justify its review cost and whether it corrects rather than reinforces agent-generated misconceptions.

Conclusion

The paper provides controlled empirical evidence that inserting semi-formal precondition and postcondition extraction before test synthesis improves LLM-agent test generation on real industrial defects. At five runs per bug, the approach raises historical bug detection from 53.4% to 63.2% and branch coverage from 46.4% to 48.9%, while maintaining essentially identical test-suite pass rates. Its strongest explanatory result is the association between Contract Coverage and detection: capturing the violated contract increases conditional detection from 19.4% to 54.9%. The gains come with a 38.0% token overhead and do not establish superiority across organizations, models, or nonhistorical testing tasks. Within the evaluated setting, however, the findings support contract extraction as a substantive semantic intervention rather than merely an additional planning format (2608.17177).

Paper to Video (Beta)

No one has generated a video about this paper yet.

Whiteboard

Explain it Like I'm 14

1. What is the paper about?

This paper studies how artificial intelligence can write better software tests.

A software test is a small program that checks whether another program behaves correctly. For example, a test might check that a shopping app rejects an invalid credit-card number.

The researchers found that AI agents often write tests that check only the obvious situations. They may miss:

  • unusual inputs,
  • error messages,
  • boundary values,
  • different paths through the code, and
  • behaviors that caused real bugs.

To improve this, the paper introduces Spec-Driven Test Generation. The idea is simple:

  1. Ask the AI to describe what the code is supposed to do.
  2. Ask it to identify what must be true before and after the code runs.
  3. Use that description to guide the AI while it writes tests.

The description is called a semi-formal specification. It is more organized than ordinary notes, but it is written in normal language rather than complicated mathematics.

2. What questions did the researchers ask?

The study focused on four main questions:

  1. Does the specification step help AI find more real bugs? The researchers compared AI-generated tests with and without the extra specification step.
  2. Are the resulting tests better quality? They examined whether the tests were easier to read, followed testing best practices, and checked more edge cases.
  3. Can the AI correctly understand the important rules of the code? In other words, can it identify the behavior that a real bug violates?
  4. Does the specification step cost much more computing effort? The researchers wanted to know whether the extra reasoning required many more words, or “tokens,” from the AI. The provided text introduces this question, but does not include its final results.

3. How was the research carried out?

Two AI approaches

The researchers used two versions of an AI coding agent. Both used the same AI model and the same programming tools.

The first was the baseline agent. It was told to:

  • read the source code,
  • create tests,
  • run the tests, and
  • fix problems in the test code.

The second was the spec-driven agent. It had two stages.

Stage 1: Understand the code

First, the agent created a specification for the code. This included:

  • Pre-conditions: things that must be true before a function runs.
  • Post-conditions: things that should be true after it finishes.
  • Undefined behavior: situations where the program does not promise a particular result.
  • Test suggestions: behaviors that should be tested but are not yet covered.

For example, imagine a function called add_customer. Its specification might say:

  • Before running, the database connection must be active.
  • If the phone number is invalid, the function must show an error.
  • If the customer is added successfully, the function should return normally.
  • An empty name should also cause an error.

The AI then marks each rule as either tested or untested.

Stage 2: Write tests

Next, the AI used the specification as a checklist. It wrote tests for the rules marked as untested.

This is similar to asking a student to make a study guide before taking a test. The study guide helps the student remember important topics instead of guessing randomly.

Real-world bug collection

The researchers tested the approach on 90 real bugs from Google software. These bugs had:

  • a buggy version,
  • a corrected version,
  • a verified failure, and
  • a known fix.

The bugs involved several programming languages, including C++, Java, Python, and Go.

To make the experiment fair, the AI:

  • saw the corrected source code,
  • did not see the bug report or the fix,
  • was given an empty test file, and
  • had to create tests from scratch.

The researchers then ran each generated test suite in two ways:

  1. On the corrected program, where the tests should pass.
  2. On the old buggy program, where a good test should fail.

A bug counted as detected if at least one generated test passed on the corrected program but failed on the buggy one.

Measuring test quality

The researchers measured several things:

  • Pass rate: whether the generated tests compiled and passed on the corrected program.
  • Line coverage: how much of the code was run by the tests.
  • Branch coverage: how many different decision paths were tested. For example, both the “yes” and “no” sides of an if statement.
  • Bug detection rate: how many historical bugs the tests found.
  • Qualitative quality: how readable the tests were, whether they followed good testing practices, and whether they included edge cases.

A stronger AI model also acted as a judge. It compared the AI-generated tests with other AI-generated tests and with tests written by human developers.

4. What did the researchers find?

The specification helped the AI find more bugs

After five independent attempts, the spec-driven agent detected 63.2% of the historical bugs. The baseline agent detected 53.4%.

That is an improvement of 9.8 percentage points.

The spec-driven agent also found 12 bugs that the baseline agent missed. The baseline agent found only 3 bugs that the spec-driven agent missed.

This suggests that writing down the expected behavior helped the AI notice less obvious problems.

The specification improved branch coverage

The two approaches had almost identical line coverage:

Measure Baseline agent Spec-driven agent
Line coverage 74.8% 74.4%
Branch coverage 46.4% 48.9%

The spec-driven agent covered slightly fewer lines overall, but it tested more decision paths. Its branch coverage was 2.5 percentage points higher.

This is important because simply running many lines does not always mean a program has been tested well. A test might run a line only in the normal case while never checking what happens when an error occurs. Branch coverage is more like checking both roads at every fork.

The generated tests were judged to be higher quality

When compared with the baseline agent’s tests, the spec-driven agent’s tests were judged better overall in 77.8% of cases.

They were especially stronger at:

  • edge-case coverage: 83.3%,
  • readability: 68.9%, and
  • following testing best practices: 65.6%.

The tests often checked boundary values, missing information, and error cases that the baseline agent ignored.

The tests were competitive with human-written tests

When compared with the original tests written by Google developers, the spec-driven tests were judged better overall in 56.7% of cases.

However, the researchers also found important differences:

  • The AI was good at writing focused tests and checking error conditions.
  • Human developers were better at very complicated situations, such as difficult state changes and time-zone calculations.
  • The AI sometimes used questionable shortcuts, such as directly calling private parts of a program.

Therefore, the AI was competitive with human tests, but it was not always better and should still be reviewed by people.

The specifications often captured the important bug rule

The researchers created a measurement called Contract Coverage. This asked whether the AI’s specification included the exact rule that the historical bug had broken.

Across five attempts, the specification captured the violated rule in 78.9% of cases.

The connection between specifications and successful bug detection was strong:

  • When the specification included the important rule, the tests found the bug in 54.9% of cases.
  • When the specification missed that rule, the tests found the bug only 19.4% of the time.

This shows that the specification acts like a useful map. If the map includes the important location, the AI is much more likely to reach it.

The extra step did not make the AI worse at writing working tests

Both agents produced tests that passed on the corrected code at nearly the same rate: 98.9% after five attempts.

This matters because the specification process improved bug-finding ability without making the AI produce more broken or uncompilable test code.

5. Why are these results important?

AI can write code quickly, but writing useful tests requires understanding what the code is supposed to do. Looking only at the code’s surface structure may cause an AI to test easy examples while missing the situations most likely to cause failures.

The paper suggests that an intermediate explanation of the code can help solve this problem. Before asking the AI to write tests, developers can ask it to create a clear contract describing:

  • valid and invalid inputs,
  • expected results,
  • error behavior,
  • changes to the program’s state, and
  • missing tests.

This could make AI coding tools more reliable and useful in real software projects. It may also produce documentation that helps human developers understand older or complicated code.

However, the results do not mean that AI-generated tests can completely replace human engineers. The study used 90 bugs from one organization, and the specifications were judged partly by another AI model. Human review is still valuable, especially for complicated algorithms, privacy concerns, and tests involving many interacting parts.

Conclusion

The main lesson is that AI writes better tests when it first explains the rules of the code.

Instead of jumping directly from source code to test code, the AI first creates a structured plan describing what should happen. This extra step helped it:

  • detect more real bugs,
  • test more decision branches,
  • find more edge cases, and
  • create tests that were often as strong as human-written tests.

In short, making the AI think through the code’s expected behavior before writing tests gives it a better chance of finding hidden problems.

Knowledge Gaps

Knowledge gaps, limitations, and open questions

The paper leaves the following issues unresolved:

  • Generalizability beyond Google: It is unclear whether the results transfer to non-Google organizations, open-source projects, smaller codebases, or domains with different testing conventions and documentation practices.
  • Representativeness of the dataset: The 90 bugs were restricted to fixes affecting one production file, one test file, and limited build configuration. This may exclude multi-file defects, architectural bugs, dependency failures, configuration errors, and other common production fault types.
  • Language-specific effects: Although the dataset includes C++, Java, Python, and Go, the paper does not report per-language results or determine whether the approach is equally effective across languages, testing frameworks, and build systems.
  • Bug-type sensitivity: The evaluation does not establish which categories of bugs benefit most from specifications. In particular, the relative effectiveness for concurrency defects, state-transition errors, numerical bugs, security vulnerabilities, API misuse, and integration failures remains unknown.
  • Limited execution budget: Only five independent sampling runs were evaluated. The performance-cost trade-off for larger budgets, repeated generation over time, or adaptive sampling is not established.
  • Unclear causal mechanism: The study shows that specifications correlate with improved detection, but does not isolate which component produces the benefit: explicit pre/post-conditions, test suggestions, additional context analysis, longer reasoning, intermediate file creation, or the prompt’s mandated workflow.
  • Unequal effective effort between agents: Although the agents use the same model and tools, the spec-driven agent may perform more repository exploration and reasoning than the baseline. The paper does not normalize token budgets, tool calls, runtime, context length, or generation effort sufficiently to show that specifications themselves cause the improvement.
  • Prompt and implementation sensitivity: The results may depend heavily on the exact prompts, tool-harness design, model version, and specification format. Robustness to alternative prompts, models, harnesses, and artifact schemas is not evaluated.
  • Model-version reproducibility: The reported use of Gemini 3 Flash and Gemini 3.1 Pro makes it difficult to determine whether the findings apply to other current or future models, especially open-weight models and stronger reasoning models.
  • No ablation of specification components: The study does not separately evaluate the effects of descriptions, pre-conditions, post-conditions, undefined behaviors, tested/untested labels, or localized test suggestions.
  • Undefined behaviors are under-evaluated: Although undefined behavior is central to the stated motivation, the formal specification tuple and the empirical analysis focus primarily on pre- and post-conditions. The contribution of explicitly documenting undefined behavior remains unmeasured.
  • No evaluation of specification correctness beyond target defects: Contract Coverage measures whether a specification captures the contract violated by one known historical bug. It does not assess whether the remaining conditions are correct, complete, non-contradictory, or aligned with actual developer intent.
  • Defect-driven metric bias: Contract Coverage is inherently tied to the selected bug and fix. A specification can receive high coverage while being wrong about other behaviors, and important contracts unrelated to the target defect are not captured by the metric.
  • Dependence on an LLM judge for specification accuracy: Contract Coverage and failure diagnoses are assessed by an LLM using the bug description, commit message, and fix diff. The judge’s interpretation may inherit ambiguity or bias from these artifacts, and no independent human validation or adjudication is reported.
  • Potential information leakage in RQ3: The judge is explicitly given the ground-truth fix diff and developer commit message. This is appropriate for post hoc assessment but may inflate apparent agreement between generated specifications and the judged contract, particularly when the fix does not uniquely determine intended behavior.
  • Reliability of qualitative evaluation remains uncertain: High agreement among five invocations of the same LLM does not establish validity, objectivity, or agreement with expert human reviewers. Inter-rater agreement with independent developers is not reported.
  • Condensed best-practice rubric validity: The testing rubric was itself produced by an LLM from internal Google documentation. The paper does not verify that the condensation preserves the source standards or that the rubric is applicable across all included languages and testing frameworks.
  • Unclear comparison with human tests: The human-authored suites were evaluated qualitatively but not under a fully controlled comparison of test scope, runtime, maintenance cost, coverage, mutation score, or bug-detection capability. Their provenance, review status, and development effort are also not characterized.
  • Greenfield setup may reduce ecological validity: Removing all existing tests creates a controlled experiment but differs from real maintenance scenarios, where agents typically extend, repair, or refactor existing test suites and can use existing tests as behavioral evidence.
  • Fixed-version source may not reflect available developer context: Agents infer intended behavior from the fixed implementation, even though real test-generation tasks may involve an evolving, partially implemented, or buggy codebase. The applicability of the method when the implementation itself is incomplete or misleading remains unresolved.
  • Historical bug detection is narrower than test quality: A test suite that fails to detect the selected historical bug may still be valuable, while a suite that detects it may contain brittle, overfitted, or semantically weak assertions. The relationship between detect@k and broader test usefulness is not established.
  • Structural coverage is an incomplete effectiveness proxy: Higher branch coverage does not necessarily imply stronger fault detection, path diversity, oracle quality, or resistance to regression. Path coverage, mutation score, semantic coverage, and regression effectiveness are not evaluated.
  • No analysis of false positives or over-specification: The paper does not quantify tests that encode incorrect assumptions, reject valid behavior, overconstrain implementation details, or pass only because they assert incidental outputs.
  • No assessment of test maintainability: The long-term maintenance burden, flakiness, execution time, duplication, dependency on private APIs, and stability under code evolution are not measured.
  • Reflection-based testing is not quantified: The paper notes that the spec-driven agent sometimes bypasses encapsulation through reflection, but does not report its frequency, consequences, or whether specification-driven generation increases this undesirable behavior.
  • Build and environment failures are incompletely characterized: Build failures are excluded from bug detection, but the paper does not report their frequency, causes, language distribution, or whether excluding them differentially favors either agent.
  • Run validity filtering may introduce selection bias: Runs that modify prohibited files are discarded without repetition. The paper does not report how often this occurs for each agent or whether invalid runs reflect meaningful differences in agent behavior.
  • Independence assumptions are unclear: The five samples for each bug use the same source, environment, prompt, and defect. The analysis does not fully explain how dependence among repeated runs is handled in confidence intervals and hypothesis tests.
  • Statistical analysis does not address multiple comparisons comprehensively: Several values of kk, coverage metrics, qualitative dimensions, and subgroup analyses are tested, but adjustment for multiple statistical comparisons is not discussed.
  • Effect heterogeneity is underexplored: Aggregate improvements conceal per-bug variation. The paper does not identify predictors of success, such as code size, complexity, documentation quality, test framework, defect severity, or contract type.
  • The reported qualitative sample is incomplete: The RQ2 analysis uses 83 successfully generated spec-driven suites rather than all 90 bugs, but the impact of excluding unsuccessful runs and the corresponding baseline suites is not fully analyzed.
  • Cost-efficiency results are missing: RQ4 is posed as a research question, but the provided results do not report token consumption, tool-call overhead, wall-clock time, monetary cost, or cost per additional bug detected.
  • Human-in-the-loop effectiveness is untested: HITL curation is presented as a key part of the framework, yet the empirical study removes it. The benefits, time requirements, reviewer agreement, and risk of human acceptance of incorrect contracts remain unknown.
  • Scalability to large components is uncertain: The framework generates specifications for every public and private unit in a source component, but the paper does not evaluate artifact size, context-window pressure, generation latency, or quality degradation on large files and repositories.
  • Cross-file and system-level contracts are insufficiently examined: The approach is described at the API and source-file level, while many behaviors depend on distributed state, callers, protocols, databases, services, or configuration. Its ability to infer and test such system-level contracts remains unresolved.
  • Future utility as documentation is unvalidated: The paper suggests that generated specifications could support human documentation and system alignment, but does not evaluate developer comprehension, editing effort, adoption, or usefulness in code review and maintenance.

Practical Applications

The paper’s main practical contribution is a two-phase workflow in which an AI agent first extracts semi-formal API contracts—descriptions, preconditions, postconditions, undefined behaviors, and test suggestions—and then generates tests from that artifact. The reported gains are strongest for branch coverage, edge-case testing, and historical bug detection; however, deployment should account for the study’s assumptions, including access to source repositories, reliable build/test tooling, reproducible bugs, and human or automated review of generated specifications.

Immediate Applications

  • Automated regression-test generation in software engineering — Industry
    • Integrate the spec-driven workflow into CI/CD systems to generate tests for newly modified production code before merge.
    • A pipeline could:
    • 1. analyze changed source files and repository documentation;
    • 2. produce a .spec.md contract artifact;
    • 3. identify untested preconditions, postconditions, and error paths;
    • 4. generate and execute tests;
    • 5. report branch coverage and whether tests fail on known or synthetic defects.
    • This is immediately actionable because the evaluated agents already use ordinary repository-navigation, file-editing, build, and test-execution tools.
    • Dependencies: reliable build environments, adequate repository context, isolation from source-code modification, and review of potentially incorrect contracts.
  • AI-assisted pull-request quality gates — Industry/software
    • Use generated specifications as an additional review artifact alongside code diffs.
    • A pull request could be blocked or flagged when:
    • newly introduced API behaviors lack documented contracts;
    • a precondition or error path is marked “Untested”;
    • branch coverage decreases;
    • generated tests do not pass against the fixed implementation.
    • The paper’s statistically significant branch-coverage improvement suggests that this workflow may identify behavioral paths that conventional line-coverage gates overlook.
    • Dependencies: organization-specific testing standards, integration with version-control systems, and safeguards against tests that pass without asserting meaningful behavior.
  • Regression testing for bug fixes — Industry
    • Given a fixed implementation and a historical defect description, the system can infer the violated contract and generate a fail-to-pass regression test.
    • This can accelerate workflows in which developers currently reproduce a bug manually, identify an expected behavior, and write a narrow regression test.
    • The reported 63.2% detect@5 rate indicates practical value as a test-generation assistant, although it is not sufficient as a sole verification mechanism.
    • Dependencies: reproducible buggy and fixed versions, trustworthy bug descriptions, and validation that generated tests fail on the buggy implementation rather than merely exercising it.
  • Test-suite gap analysis and maintenance — Industry
    • Generate a living contract inventory for public and private APIs, labeling each condition as tested or untested.
    • Teams could use this inventory to prioritize:
    • missing validation tests;
    • exceptional and fallback paths;
    • boundary-value tests;
    • state and side-effect assertions;
    • behavior affected by configuration or optional inputs.
    • This is particularly useful for legacy systems with incomplete documentation or fragmented test suites.
    • Dependencies: access to callers, comments, docstrings, protocol specifications, and existing tests; inferred intent may be ambiguous in poorly documented systems.
  • Developer documentation and onboarding — Industry/academia
    • Store the generated .spec.md files as human-readable API documentation describing expected inputs, outputs, side effects, failures, and undefined behavior.
    • Such documents could support code review, maintenance, onboarding, and impact analysis without requiring developers to reconstruct behavior solely from implementation details.
    • Dependencies: contracts must be reviewed and versioned; otherwise, the system may document accidental or buggy implementation behavior as intended behavior.
  • Human-in-the-loop test design — Industry
    • Insert a review stage between specification extraction and test synthesis.
    • Developers can amend incorrect preconditions, reject inappropriate test suggestions, add business rules, and explicitly resolve undefined behaviors before code generation.
    • This directly operationalizes the paper’s proposed HITL design and is particularly suitable for safety-critical, financial, and security-sensitive software.
    • Dependencies: developer review capacity, clear ownership of behavioral requirements, and interfaces that make contract corrections easy to audit.
  • Edge-case and negative-path test generation — Healthcare, finance, infrastructure, and enterprise software
    • Apply the workflow to APIs involving invalid inputs, authorization failures, missing fields, resource limits, retries, fallbacks, and exceptional states.
    • The paper reports that spec-driven tests were preferred for edge-case coverage in 83.3% of comparisons with the baseline, making this approach especially relevant where failures occur at behavioral boundaries rather than normal execution paths.
    • Dependencies: domain rules must be available to the agent; generated tests should use synthetic or de-identified data and must not expose confidential information.
  • Multi-language test automation — Software engineering
    • Deploy a common specification format across C++, Java, Python, Go, and potentially other languages while retaining language-specific test-generation backends.
    • A shared contract artifact can provide a language-independent representation of expected behavior for polyglot repositories and services.
    • Dependencies: language-specific build systems, testing idioms, mocking frameworks, and model competence; the paper demonstrates only a limited set of languages and repository conditions.
  • Research and teaching tools for design by contract — Academia
    • Use the framework in software-engineering courses to teach:
    • preconditions and postconditions;
    • test oracles;
    • boundary-value analysis;
    • branch coverage;
    • the distinction between implementation behavior and intended behavior.
    • Students could compare direct test generation with contract-mediated generation and inspect where an inferred contract fails.
    • Dependencies: educational deployments should emphasize that LLM-generated specifications are hypotheses requiring verification, not formal proofs.
  • Policy and organizational governance for coding agents — Policy/management
    • Establish policies requiring coding agents to produce an inspectable behavioral rationale or contract before modifying tests in sensitive repositories.
    • Organizations can require logging of:
    • source context consulted;
    • generated conditions;
    • accepted or rejected suggestions;
    • tests executed;
    • coverage and defect-detection results.
    • This improves auditability and makes agentic test generation more compatible with regulated development processes.
    • Dependencies: governance rules must define acceptable evidence, data-retention limits, and human accountability; semi-formal contracts do not by themselves guarantee correctness or compliance.

Long-Term Applications

  • Formal verification and theorem-prover integration — Software verification/academia
    • Translate reviewed natural-language contracts into formal specifications for tools such as SMT solvers, Lean, or language-specific verification systems.
    • A future workflow could use the semi-formal artifact as an intermediate representation for:
    • precondition checking;
    • invariant inference;
    • symbolic execution;
    • formal postcondition verification;
    • proof-obligation generation.
    • The paper explicitly identifies compatibility with backends such as Lean and SMT-LIB as a future direction.
    • Dependencies: unambiguous formalization, domain-specific semantics, handling of concurrency and side effects, and mechanisms for detecting contradictions in natural-language contracts.
  • Continuous contract mining and behavioral-drift detection — Industry/software
    • Maintain contracts across successive releases and compare them with implementation changes, API usage, production traces, and test results.
    • The system could alert teams when:
    • an implementation violates a documented postcondition;
    • a public API’s behavior changes without a specification update;
    • callers rely on undocumented behavior;
    • a previously tested condition becomes uncovered.
    • Dependencies: versioned contracts, reliable change-impact analysis, and careful distinction between intentional behavior changes and regressions.
  • Production-observability-to-test workflows — Cloud and distributed systems
    • Combine generated contracts with logs, traces, API schemas, incident reports, and runtime assertions to produce tests for distributed failure modes.
    • Potential outputs include tests for retries, timeouts, ordering constraints, partial failures, idempotency, and protocol-state violations.
    • This extends the approach beyond single-file bugs, which were the dominant constraint in the study.
    • Dependencies: privacy-preserving telemetry, reproducible distributed environments, deterministic replay, and models capable of reasoning about asynchronous and cross-service behavior.
  • Autonomous test prioritization and repair — Software quality assurance
    • Use Contract Coverage as a prioritization signal: conditions linked to historically violated contracts could receive more generation attempts, execution budget, mutation analysis, or human review.
    • A future system could distinguish specification-generation failures from test-generation failures and automatically select the appropriate remedy:
    • gather more repository context;
    • ask a developer for clarification;
    • generate additional tests;
    • invoke symbolic or fuzz testing.
    • Dependencies: stronger causal validation of Contract Coverage, calibrated confidence estimates, and safeguards against optimizing only for previously observed defect types.
  • Domain-specific compliance and safety testing — Healthcare, finance, automotive, aerospace, and energy
    • Encode regulatory, safety, and operational requirements as reviewed contracts and generate tests for prohibited states, required warnings, authorization constraints, resource limits, and fail-safe behavior.
    • Examples include:
    • healthcare: validation of consent, data-access, and clinical workflow states;
    • finance: transaction limits, authorization, rounding, and rollback behavior;
    • energy: safety interlocks, operating thresholds, and fault recovery;
    • automotive or aerospace: mode transitions and degraded-operation behavior.
    • Dependencies: domain experts must validate the contracts; certification authorities may require deterministic evidence, traceability, and formal assurance beyond LLM-generated tests.
  • Robotics and cyber-physical systems — Robotics/embedded engineering
    • Represent controller and hardware-interface contracts, including sensor validity ranges, actuator limits, timing assumptions, safety stops, and state-transition rules.
    • Generated tests could operate in simulation before deployment and target boundary conditions that are difficult to reproduce physically.
    • Dependencies: high-fidelity simulators, real-time guarantees, hardware-in-the-loop infrastructure, and explicit treatment of nondeterminism and physical uncertainty.
  • Security-oriented contract testing — Cybersecurity
    • Generate tests for authorization boundaries, malformed inputs, privilege transitions, protocol states, resource exhaustion, and secure error handling.
    • Semi-formal contracts could serve as a bridge between API specifications and security regression suites.
    • Dependencies: security review is essential because an agent may infer incomplete or unsafe behavior; generated tests should be supplemented with fuzzing, penetration testing, threat modeling, and vulnerability-specific analysis.
  • Large-scale software-agent orchestration — Industry/research
    • Build multi-agent systems in which separate agents perform contract extraction, contract critique, test generation, execution, and adjudication.
    • One agent could propose a contract, another could search for counterexamples, and a third could generate tests only after disagreements are resolved.
    • This may reduce the specification omissions identified in the paper, such as missing error handling, omitted data transformations, abstracted constants, and missing execution constraints.
    • Dependencies: increased inference cost, coordination protocols, reproducible evaluations, and mechanisms preventing correlated errors across agents using similar models.
  • Benchmarking and evaluation standards for coding agents — Academia/industry policy
    • Adopt defect-driven metrics such as detect@k, branch coverage, pass rate, and Contract Coverage in evaluations of AI coding systems.
    • Historical production bugs provide a more meaningful benchmark than purely synthetic mutations, while specification accuracy helps separate failures of reasoning from failures of code synthesis.
    • Dependencies: representative and legally shareable datasets, reproducible environments, unbiased judges, and stronger human-validated ground truth than LLM-as-a-Judge alone.
  • Everyday developer productivity and personal software projects — Daily life
    • IDE plugins could automatically generate a concise contract and targeted tests when a user writes or modifies a function.
    • The tool could explain assumptions such as accepted input ranges, expected errors, side effects, and cases not covered by tests, helping non-experts detect defects earlier.
    • Dependencies: local execution permissions, protection of proprietary code, low enough latency and cost, and clear warnings that generated tests may encode incorrect assumptions.

Overall, the most deployable near-term use is contract-grounded regression and unit-test generation integrated with human review and CI. Broader applications—especially formal verification, safety certification, distributed systems, and autonomous software maintenance—depend on improving specification accuracy, validating inferred intent, reducing model and judge bias, and extending evaluation beyond the paper’s 90 single-file historical bugs.

Glossary

  • Abstraction: The process of hiding implementation details while retaining a simplified conceptual representation. “Abstraction of Constants”
  • Agentic harness: The execution environment and tools used to support an AI agent’s interaction with a codebase. “operate within an identical agentic harness equipped with the following tool set”
  • API (Application Programming Interface): A defined interface through which software components communicate or are accessed. “a semi-formal contract for an API”
  • Arrange-Act-Assert: A unit-testing structure that separates test setup, execution, and verification. “adherence to the Arrange-Act-Assert pattern”
  • Behavior-driven testing: A testing approach that focuses on externally observable behaviors and states rather than implementation methods. “behavior-driven testing (focusing on testing distinct behaviors and states rather than methods)”
  • Behavioral contract: A description of the conditions and guarantees governing a program component’s behavior. “the underlying behavioral contracts”
  • Bi-modal distribution: A probability distribution with two distinct concentrations or peaks. “a heavily bi-modal distribution”
  • Bootstrapping: A statistical resampling method used to estimate uncertainty by repeatedly sampling from observed data. “we perform bootstrapping at the bug level”
  • Branch coverage: The proportion of executable control-flow branches exercised by a test suite. “a 2.5 percentage point improvement in branch coverage”
  • Caller-site: A location in a codebase where a function or API is invoked. “caller-site API usage patterns across the repository”
  • Cognitive scaffold: An intermediate structure that guides reasoning by organizing information or constraints. “This intermediate semi-formal specification acts as a cognitive scaffold”
  • Confounding variable: A factor that can affect an observed relationship and obscure the effect being studied. “This removes test generation capability as a confounding variable”
  • Contingency table: A table that records the frequencies of combinations of categorical outcomes. “we construct a 2x2 contingency table”
  • Contract Coverage: A defect-oriented metric measuring whether a specification captures the behavioral condition violated by a bug. “Contract Coverage serves as a pragmatic, defect-driven proxy”
  • DAMP (Descriptive and Meaningful Phrases): A testing principle favoring clear, descriptive repetition over unnecessary abstraction. “prioritizing DAMP (``Descriptive and Meaningful Phrases'') over DRY”
  • DbC (Design by Contract): A software-development methodology that specifies component obligations through preconditions, postconditions, and invariants. “Design by Contract (DbC) explicitly documents behaviors”
  • Defects4J: A benchmark dataset and framework containing real Java software defects for evaluating automated program-repair and testing techniques. “foundational evaluation frameworks like Defects4J”
  • detect@k: The proportion of bugs detected by at least one test suite among kk independent generation attempts. “Fault Detection Rate (detect@k)”
  • Edge-case coverage: The extent to which tests exercise unusual, extreme, or boundary conditions. “edge-case coverage”
  • Evaluation tautology: A circular evaluation situation in which a system can derive the expected answer directly from information it should not access. “To prevent evaluation tautology”
  • Fail-to-Pass validation: A procedure that checks whether tests pass on corrected code and fail on the corresponding buggy implementation. “via Fail-to-Pass validation”
  • Fisher’s exact test: A statistical test for association between categorical variables, especially suitable for small or fixed samples. “we evaluate association using the Phi coefficient and assess significance via Fisher's exact test”
  • Greenfield Test Generation: Test generation performed without access to pre-existing tests for the target code. “we employ a Greenfield Test Generation setup”
  • HITL (Human-in-the-Loop): An arrangement in which a human reviews or modifies an automated system’s intermediate output. “our framework naturally supports an optional Human-in-the-Loop (HITL) step”
  • Inference parameters: Settings controlling the behavior of a generative model during output production. “both agents use the default Gemini 3 Flash inference parameters”
  • Invariant: A property that remains true throughout the execution or operation of a program. “pre-/post-conditions, and invariants”
  • LLM-as-a-Judge: An evaluation method in which a LLM assesses the quality of another system’s outputs. “Using LLM-as-a-Judge”
  • McNemar’s test: A statistical test for comparing paired binary outcomes. “We apply McNemar’s test to determine if the differences in detection rates are statistically significant”
  • Mutation score: A testing metric based on the proportion of artificially introduced program changes detected by a test suite. “software testing literature frequently relies on mutation scores”
  • Non-determinism: Variation in system outputs or behavior across otherwise equivalent executions. “To account for the inherent non-determinism of LLM”
  • Oracle: A mechanism or specification that determines whether a program’s behavior is correct. “This specification then acts as an oracle”
  • Post-condition: A condition guaranteed to hold after a program operation completes. “A set of post-conditions that define the guaranteed state after execution”
  • Pre-condition: A condition or constraint required to hold before a program operation begins. “A set of pre-conditions that define the exact state or constraints required before execution”
  • Prompt-to-code: A code-generation approach in which an agent directly produces implementation or test code from instructions. “The baseline is a standard prompt-to-code agent”
  • Protocol RFC: A formal technical document specifying the design or behavior of a protocol. “protocol RFCs”
  • Reverse-patching: Reapplying a prior buggy implementation to code that contains a corrective change. “The agent's workspace is reverse-patched to the original buggy implementation”
  • Semantic completeness: The extent to which a specification captures all behaviorally relevant meanings or conditions of a system. “we evaluate the semantic completeness of the generated specs”
  • Semantic drift: The gradual divergence between an implementation, specification, or inferred intent and the intended meaning. “Synthesizing a contract from these intent sources restricts semantic drift”
  • SMT-LIB: A standardized language for expressing satisfiability-modulo-theories problems to automated theorem provers. “Lean~\cite{de2015lean} or SMT-LIB~\cite{BarFT-SMTLIB}”
  • Specification artifact: A structured document representing the inferred behavioral contract of a code component. “we define the specification artifact for a given source code component”
  • State space: The set of possible states a program or system can occupy during execution. “generate superficial tests that fail to systematically exercise the program's state space”
  • Structural coverage: The proportion of a program’s structural elements, such as lines or branches, executed by tests. “We evaluate structural coverage using the average line and branch coverage”
  • TopK: A sampling parameter limiting token selection to the KK most probable candidates during language-model generation. “Temperature 1.0, TopP 1.0, and TopK 50”
  • TopP: A sampling parameter that selects tokens from the smallest probability set whose cumulative probability exceeds a specified threshold. “Temperature 1.0, TopP 1.0, and TopK 50”
  • Wilcoxon signed-rank test: A nonparametric statistical test for comparing paired continuous measurements. “We use this paired difference test to compare line coverage distributions and branch coverage distributions”
  • Undefined behavior: Program behavior for which the language, specification, or system provides no defined result or guarantee. “pre-conditions, post-conditions, and undefined behaviors”

Open Problems

We haven't generated a list of open problems mentioned in this paper yet.

Tweets

Sign up for free to view the 2 tweets with 372 likes about this paper.