Navigating the Labyrinth: Path-Sensitive Unit Test Generation with Large Language Models

📄 arXiv: 2509.23812v2 📥 PDF

作者: Dianshu Liao, Xin Yin, Shidong Pan, Chao Ni, Zhenchang Xing, Xiaoyu Sun

分类: cs.SE, cs.AI

发布日期: 2025-09-28 (更新: 2025-10-11)


💡 一句话要点

JUnitGenie:利用大语言模型实现路径敏感的单元测试生成,提升代码覆盖率。

🎯 匹配领域: 支柱九:具身大模型 (Embodied Foundation Models)

关键词: 单元测试生成 大语言模型 路径敏感 代码覆盖率 软件质量保证 自动化测试 Java项目

📋 核心要点

  1. 现有单元测试生成方法,如启发式或LLM方法,缺乏路径敏感性,难以覆盖复杂控制流。
  2. JUnitGenie框架结合代码知识与LLM语义能力,通过结构化提示指导生成高覆盖率单元测试。
  3. 实验表明,JUnitGenie在真实Java项目中显著提升分支和行覆盖率,并能发现真实错误。

📝 摘要(中文)

单元测试对于软件质量保证至关重要,但编写和维护测试用例既耗时又容易出错。为了解决这个问题,研究人员提出了各种自动化单元测试生成技术,包括传统的基于启发式的方法和最近利用大型语言模型(LLM)的方法。然而,这些现有方法本质上是路径不敏感的,因为它们依赖于固定的启发式方法或有限的上下文信息,并且无法推断深层的控制流结构。因此,它们通常难以实现足够的覆盖率,特别是对于深度或复杂的执行路径。在这项工作中,我们提出了一个路径敏感的框架JUnitGenie,通过结合代码知识和LLM的语义能力来指导上下文感知的单元测试生成,从而填补了这一空白。在从Java项目中提取代码知识后,JUnitGenie将这些知识提炼成结构化的提示,以指导生成高覆盖率的单元测试。我们在来自十个真实Java项目的2,258个复杂焦点方法上评估了JUnitGenie。结果表明,JUnitGenie生成有效的测试,并且与基于启发式和基于LLM的基线相比,平均提高了29.60%的分支覆盖率和31.00%的行覆盖率。我们进一步证明,生成的测试用例可以发现真实世界的错误,这些错误后来被开发人员确认并修复。

🔬 方法详解

问题定义:现有单元测试生成方法,无论是基于启发式规则还是基于大型语言模型,都难以有效处理复杂代码中的深层控制流。这些方法缺乏对代码执行路径的敏感性,导致生成的测试用例无法充分覆盖代码的各种执行情况,尤其是在代码逻辑复杂、嵌套层级深的情况下,测试覆盖率往往不足,难以发现潜在的bug。

核心思路:JUnitGenie的核心思路是将代码知识显式地融入到LLM的提示(prompt)中,从而引导LLM生成更具上下文感知能力和路径敏感性的单元测试。通过提取Java项目的代码知识,并将其转化为结构化的提示,JUnitGenie能够让LLM更好地理解被测代码的逻辑和可能的执行路径,从而生成更有针对性的测试用例。

技术框架:JUnitGenie框架主要包含以下几个阶段:1) 代码知识提取:从Java项目中提取类、方法、变量等代码元素及其相互关系。2) 提示构建:将提取的代码知识转化为结构化的提示,包括方法签名、参数类型、控制流信息等。3) LLM调用:将构建的提示输入到LLM中,生成单元测试代码。4) 测试验证:对生成的单元测试代码进行编译和执行,验证其有效性。5) 覆盖率评估:评估生成的单元测试代码的覆盖率,并根据覆盖率结果进行迭代优化。

关键创新:JUnitGenie最重要的技术创新点在于其路径敏感的提示构建方法。与传统的提示方法不同,JUnitGenie不仅关注被测方法的代码本身,还关注其可能的执行路径和控制流。通过将这些信息融入到提示中,JUnitGenie能够引导LLM生成更具针对性的测试用例,从而提高测试覆盖率。

关键设计:JUnitGenie的关键设计包括:1) 代码知识提取策略:如何有效地提取代码中的关键信息,并将其转化为LLM可以理解的格式。2) 提示结构设计:如何设计提示的结构,使其既能包含足够的信息,又能避免LLM产生混淆或错误。3) LLM选择与调优:选择合适的LLM,并对其进行调优,以提高生成单元测试代码的质量和效率。4) 覆盖率评估指标:选择合适的覆盖率评估指标,并根据覆盖率结果进行迭代优化。

🖼️ 关键图片

fig_0
fig_1
fig_2

📊 实验亮点

实验结果表明,JUnitGenie在10个真实Java项目的2258个复杂方法上进行了评估,与基于启发式和基于LLM的基线方法相比,JUnitGenie平均提高了29.60%的分支覆盖率和31.00%的行覆盖率。此外,JUnitGenie生成的测试用例还成功发现了真实世界中的bug,这些bug已被开发人员确认并修复。

🎯 应用场景

JUnitGenie可应用于软件开发过程中的单元测试环节,帮助开发人员自动生成高质量的测试用例,提高代码覆盖率,减少bug数量,从而提升软件质量。该研究成果对于提高软件开发效率、降低软件维护成本具有重要意义,并有望推动自动化测试技术的发展。

📄 摘要(原文)

Unit testing is essential for software quality assurance, yet writing and maintaining tests remains time-consuming and error-prone. To address this challenge, researchers have proposed various techniques for automating unit test generation, including traditional heuristic-based methods and more recent approaches that leverage large language models (LLMs). However, these existing approaches are inherently path-insensitive because they rely on fixed heuristics or limited contextual information and fail to reason about deep control-flow structures. As a result, they often struggle to achieve adequate coverage, particularly for deep or complex execution paths. In this work, we present a path-sensitive framework, JUnitGenie, to fill this gap by combining code knowledge with the semantic capabilities of LLMs in guiding context-aware unit test generation. After extracting code knowledge from Java projects, JUnitGenie distills this knowledge into structured prompts to guide the generation of high-coverage unit tests. We evaluate JUnitGenie on 2,258 complex focal methods from ten real-world Java projects. The results show that JUnitGenie generates valid tests and improves branch and line coverage by 29.60% and 31.00% on average over both heuristic and LLM-based baselines. We further demonstrate that the generated test cases can uncover real-world bugs, which were later confirmed and fixed by developers.