LISP:基于大语言模型的库API输入空间划分测试技术
本文完整解析ICSE’25论文提出的创新测试工具LISP,通过大语言模型实现智能化的API测试
什么是LISP?
LISP(LLM based Input Space Partitioning)是一项突破性的软件测试技术。它能利用大语言模型(LLM)深入理解库API的代码逻辑,并基于这种理解自动完成输入空间的智能划分。简单来说,它让AI像专业测试工程师一样分析代码,自动生成高质量的测试用例。
技术亮点
-
🧠 代码理解能力:LLM直接分析API源代码 -
📊 智能分区策略:基于代码语义划分输入空间 -
💡 常识知识融合:结合通用领域知识优化测试 -
🏆 学术认可:入选软件工程顶会ICSE 2025
项目已通过ACM科研复现认证
环境配置指南(手把手安装)
系统要求
组件 | 要求 |
---|---|
操作系统 | Ubuntu 20.04/22.04 (x86架构) |
内存 | ≥4 GB RAM |
Java | JDK 11+ |
Python | 3.10+ |
构建工具 | Maven 3.6+ |
安装四步曲
-
安装Java依赖
进入llm-JQF
目录执行:mvn install -DskipTests
-
配置API密钥
在llm-JQF
目录运行:sh set-key.sh -k <Your_API_Key> -b https://api.openai.com/v1
💰 成本提示:完整运行约需$40的OpenAI token费用
-
安装Python依赖
进入llm-seed-generator
目录执行:pip3 install -r requirements.txt
-
准备测试API
预置2205个API方法签名位于:LISP/llm-JQF/signs/ ├── commons-lang3 ├── guava └── ...
实战操作手册
核心工具
主执行文件位于:./llm-JQF/bin/jqf-llm
关键参数说明:
-i # 启用覆盖率统计
-o # 输出覆盖率结果
-l # 指定签名文件(批量测试)
-s # 实验模式选择:
# cg → LISP-CG模式
# skipUnder → 消融实验1
# skipEP → 消融实验2
# basic → LLM基线测试
单API测试示范
测试Guava库的Longs.min方法:
bin/jqf-llm -i -o "com.google.guava:guava:32.1-jre" \
"com.google.common.primitives.Longs.min(long[])"
成功输出示例:
Semantic Fuzzing with LLM
--------------------------
Test signature: org.apache.commons.lang3.ArrayUtils.addAll(boolean[],boolean[])
Elapsed time: 3s
Number of executions: 4
Valid inputs: 4 (100.00%)
Unique failures: 0
API Coverage: 11 branches (100.00% of 11)
Total Coverage: 16 branches (100.00% of 16)
批量测试流程
注意:文件中所有API必须属于同一库
bin/jqf-llm -i -o -l signs/guava -s cg \
"com.google.guava:guava:32.1.2-jre"
结果深度解析
结果目录结构
result/
├── commons-lang3_cg_1737620727667.json # 概要报告
└── details/
├── commons-lang3/
│ ├── cg/
│ │ ├── ArrayUtils.addAll(...)0/
│ │ │ ├── coverage_hash # 覆盖路径哈希
│ │ │ ├── detail.json # 详细数据
│ │ │ ├── graph.json # 方法调用图
│ │ │ ├── input_generator # LLM生成的输入
│ │ │ ├── llm_output.log # LLM交互日志
│ │ │ └── RunCode.java # 测试用例代码
关键数据文件说明
1. 概要报告(JSON格式)
{
"coverage":1.0, // 覆盖率
"coveredEdge":11, // 覆盖分支数
"generatedInputsNum":6, // 生成输入总数
"inputToken":9449, // 输入token消耗
"outputToken":969, // 输出token消耗
"runTime":27950, // 运行时间(ms)
"successAPINum":1, // 成功测试API数
"totalEdge":11, // 总分支数
"unexpectedBehaviorNum":0 // 异常行为数
}
2. 详细数据(detail.json)
包含方法级别的:
-
分支覆盖详情 -
执行路径记录 -
异常行为日志 -
token消耗明细
实验评估方法论
RQ1:代码覆盖能力
-
评估指标:分支覆盖率 -
数据源: -
概要报告的 coverage
字段 -
detail.json中的分支覆盖详情
-
-
分析重点:LISP与传统方法的覆盖率对比
RQ2:错误检测能力
-
评估指标:异常行为数量 -
数据源: -
概要报告的 unexpectedBehaviorNum
-
detail.json中的异常堆栈信息
-
-
分析重点:检测到的边界条件错误
RQ3:执行成本分析
-
核心指标: -
Token消耗(inputToken/outputToken) -
执行时间(runTime)
-
-
优化方向:降低LLM交互成本
RQ4:消融实验设计
模式参数 | 测试内容 |
---|---|
-s cg | 完整LISP-CG |
-s skipUnder | 消融实验1 (ISP+OI) |
-s skipEP | 消融实验2 (TDA+OI) |
-s basic | LLM基线方法 |
技术问答(FAQ)
Q1:为什么需要4GB内存?
A:LLM推理和代码分析需要较大内存空间,实测低于4GB会导致OOM错误
Q2:如何查看具体的测试输入?
A:在details/<库名>/<模式>/<方法名>/input_generator
文件中查看LLM生成的原始输入
Q3:token成本如何预估?
A:参考公式:
总成本 ≈ (inputToken/1000)×$0.01 + (outputToken/1000)×$0.03
Q4:能测试私有方法吗?
A:目前仅支持public API,私有方法需通过公有接口间接测试
Q5:结果中的coverage_hash有什么用?
A:用于快速比对不同运行的覆盖路径差异,避免重复计算
结语:测试技术的智能化演进
LISP代表了API测试领域的范式转变:
-
人机协作:结合LLM的代码理解与人类测试经验 -
动态分区:基于代码语义的智能输入空间划分 -
知识融合:将通用领域知识注入测试过程 -
量化评估:通过四维度研究问题系统验证效果