cpp-utgen 是一个面向 C/C++ 项目的大模型单元测试生成工具。它结合 LLVM/Clang 静态分析结果生成 GoogleTest,并对每个测试依次执行编译、运行和大模型修复,最终筛选可用测试、统计覆盖率并导出测试集。
目标项目源码 + compile_commands.json
|
v
brinfo / focxt / include-finder
|
v
大模型生成 GoogleTest
|
v
逐测试:编译 -> 编译修复 -> 运行 -> 测试修复
|
v
filter_manifest.json 记录状态
|
v
覆盖率统计 + 可用测试导出
默认流程在每个 test_*.cpp 生成后立即进入检查闭环:
- 编译失败时调用大模型修复,并重新编译候选。
- 编译通过后运行测试;断言、Mock、异常、崩溃和超时等失败会进入测试修复。
- 编译修复和测试修复共享单测试修复轮数,默认最多 10 轮。
- 最终通过的测试标记为
kept=true;仍失败的测试标记为kept=false,原文件不会被删除。 - 只有状态有效且最终保留的测试参与覆盖率统计,并导出到
filtered_tests*。
工具生成四类测试,用于对比路径需求和项目上下文对生成结果的影响:
| 类型 | 输出目录 | 路径测试需求 | 项目上下文 |
|---|---|---|---|
| 基础生成 | llm_tests |
否 | 否 |
| 上下文增强 | llm_tests_cxt |
否 | 是 |
| 需求增强 | llm_tests_req |
是 | 否 |
| 需求与上下文增强 | llm_tests_req_cxt |
是 | 是 |
| 路径 | 说明 |
|---|---|
utgen/ |
Python 主程序、逐测试工作流、编译/运行修复和覆盖率统计。 |
analysis-tools/ |
可独立构建的 brinfo、focxt、include-finder Clang Tooling 工具。 |
docs/palm-cpp-unit-test-generation.md |
技术路线、模块设计、数据结构和完整运行说明。 |
pyproject.toml、uv.lock |
Python 3.12 环境和锁定依赖。 |
静态分析工具直接链接已安装的 LLVM/Clang 17 开发包,不需要下载完整 LLVM 源码树。构建细节及 macOS 安装方法见 静态分析工具说明。
- uv 和 Python 3.12;项目依赖由
uv.lock锁定。 - CMake 3.20 或更高版本、Ninja,以及可编译目标项目的 C/C++ 工具链。
- LLVM/Clang 17 开发包、
clang-scan-deps和clangd-indexer。 - GoogleTest、CTest,以及覆盖率阶段使用的
gcov、lcov和genhtml。 - 可访问的 OpenAI 兼容大模型接口。
macOS 建议通过 Homebrew 安装 llvm@17、CMake、Ninja、uv 和 lcov。Homebrew 的 llvm@17 不包含 clangd-indexer,需按 macOS 配置说明 单独安装官方 LLVM 17 系列索引工具。
以下命令均在仓库根目录执行。
uv sync --frozenuv 会按照 .python-version 和 uv.lock 创建或更新根目录下的 .venv,无需手动激活虚拟环境。
将路径替换为本机 LLVM/Clang 17 的 CMake 包目录:
cmake -S analysis-tools -B analysis-tools/build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_DIR=/path/to/llvm/lib/cmake/llvm \
-DClang_DIR=/path/to/llvm/lib/cmake/clang
cmake --build analysis-tools/build
ctest --test-dir analysis-tools/build --output-on-failureCMake 默认从 LLVM 安装前缀识别 Clang 内建头文件目录;非标准布局可额外传入
-DCPP_UTGEN_CLANG_RESOURCE_DIR="$(/path/to/clang-17 -print-resource-dir)"。该目录会记录在分析工具中,移动 LLVM 安装后应重新配置并构建。
可以直接使用构建目录中的可执行文件,也可以统一安装:
cmake --install analysis-tools/build --prefix "$HOME/.local"
export PATH="$HOME/.local/bin:$PATH"include-finder 由 Python 主流程从 PATH 查找;若不安装,请把 analysis-tools/build/include-finder 加入 PATH。
在 utgen/ 下创建不会被 Git 跟踪的 config_private.py:
import os
URL = "https://your-llm-endpoint/v1/chat/completions"
API_KEY = "your-api-key"
MODEL = "your-model-name"
LIBCLANG_PATH = "/path/to/libclang.so" # macOS 使用 libclang.dylib
BRINFO_PATH = "/path/to/brinfo"
FOCXT_PATH = "/path/to/focxt"
CPU_COUNT = os.cpu_count() or 4
CLANG_SCAN_DEPS_PATH = "/path/to/clang-scan-deps"
CLANGD_INDEXER_PATH = "/path/to/clangd-indexer"MODEL 用于选择 OpenAI 兼容接口提供的聊天补全模型。libclang 动态库、Python clang 绑定和各分析工具应统一使用 LLVM 17 系列。请勿把 API Key 或本机绝对路径写入会提交的 utgen/config.py。
目标 C/C++ 项目需要能够生成编译数据库:
cmake -S /path/to/project -B /path/to/project/build -G Ninja \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON目标项目还需要启用 CTest 和 GoogleTest、接入四类 llm_tests* 子目录及 llm_coverage,并准备覆盖率配置。完整 CMake 示例和 ctest.sh 说明见 准备目标 C/C++ 项目。
uv run --frozen python utgen/decldef.py \
-p /path/to/project \
-b /path/to/project/build该步骤调用 clang-scan-deps 和 clangd-indexer,在目标项目的 project_info/ 中生成依赖、声明和定义数据。仅在已有 deps.json 与 decl_def.yaml 时才使用 --no-preprocess。
uv run --frozen python utgen/main.py \
-p /path/to/project \
-b /path/to/project/build \
--max-repair-rounds 10 \
--repair-choices 3 \
--test-timeout 600该命令完成项目分析、四类测试生成、逐测试编译与运行修复、最终复验、覆盖率统计和测试导出。只生成需求与上下文增强测试时添加 -t req-cxt;-t base 表示无后缀的 llm_tests。-t 可重复指定,省略时处理全部四类。项目级生成会产生较多大模型调用,建议先用小型目标项目验证工具链和配置。
所有产物均写入目标项目,而不是本仓库:
| 产物 | 说明 |
|---|---|
llm_reqs/、*_cxt.json |
brinfo 与 focxt 的静态分析结果。 |
includes.json |
include-finder 收集的项目内头文件。 |
llm_tests* |
全部生成测试、修复结果、日志和失败测试;C 源码的测试也使用 .cpp GoogleTest。 |
llm_tests*/filter_manifest.json |
每个测试的编译、运行、修复轮数、文件哈希和 kept 状态。 |
filtered_tests* |
仅包含最终编译通过、运行通过且状态有效的测试。 |
result*.csv |
四类生成策略对应的编译、测试和覆盖率统计。 |
llm_coverage/ |
覆盖率目标及运行产物。 |
project_info/ |
源文件依赖、声明与定义映射等预处理结果。 |
测试目录层级、命名方式、GoogleTest 格式以及 Mock/异常示例见 单元测试用例格式规范。
# 复用已有 brinfo/focxt 分析结果,重新生成测试
uv run --frozen python utgen/main.py -p /path/to/project -b /path/to/project/build --no-analysis
# 不重新生成测试,对已有产物执行完整后处理
uv run --frozen python utgen/main.py -p /path/to/project -b /path/to/project/build --post-analysis
# 对已有产物分别执行编译检查、运行检查和导出
uv run --frozen python utgen/main.py -p /path/to/project -b /path/to/project/build --compile-only
uv run --frozen python utgen/main.py -p /path/to/project -b /path/to/project/build --test-only
uv run --frozen python utgen/main.py -p /path/to/project -b /path/to/project/build --export-only默认主流程已自动调用编译修复和测试修复。compile_repair.py、test_repair.py 主要用于处理旧产物或人工控制阶段;详细参数见 UTGen 使用说明。
- 主流程会注释目标项目中的
main、test、tests函数并生成.bak文件,建议在目标项目的临时副本、容器或干净 Git 工作树中运行。 compile_commands.json是静态分析和测试编译的核心输入,路径错误或内容过期会导致后续阶段失败。- 失败测试不会被物理删除;是否保留由
filter_manifest.json中的状态决定。 - 修改
llm_tests*中的测试后,旧哈希状态会失效,需要重新执行编译和运行检查才能导出。 --batch-workflow可复现“全部生成后统一检查”的历史流程;新任务建议使用默认逐测试闭环。- macOS 上的覆盖率工具兼容性取决于目标项目所用编译器,正式运行前应先用小型项目验证
gcov与 lcov 链路。