Record 202307¶
1 算法¶
类过滤器:
anonymousMethodFilterabstractClassFilter
函数过滤器:
constructorMethodFilteranonymousClassFilterabstractMethodFilter
1.1 初始种群生成¶
问题:
- EvoSuite 怎么实现的?论文?
- 个体的方法调用序列是什么序列?
- EvoSuite 实际生成的测试用例是怎么样的?
1.2 选择¶
1.3 突变¶
1.4 重组¶
2 框架¶
2.1 断言生成¶
限制:仅适用于基础数据类型的返回值
进度:
- 使用
print语句获取方法调用返回结果 - 通过
OutputStream获取返回结果的类型和值,并存储在TestCase中 -
TestCase转化为Jimple时生成断言
方案 1
- 生成正常的 jasmin class;
- 使用 java agent 做插桩,收集待测方法的返回值;
- 插桩信息返回:
- 使用 socket 将返回值传给算法;
- 使用 java agent 在测试用例方法体的最后添加
print语句,通过outputStream的方式传给算法。
方案 2
TestCase转化为SootMethod时,如果最后一个方法调用有基础数据类型的返回值,则添加print语句将方法调用的结果输出(仅在遗传算法中做此特殊转换);- 获取 fitness 时,通过
outputStream的方式获取方法调用的输出。
2.2 Android Test 生成¶
问题:
- 如何在命令行中运行 android test?
- 如何获取覆盖率?
- 如何判断是否为 android test?
- 怎么样的 android test 是有意义的?
2.3 测试用例约简¶
2.4 测试用例重用¶
3 进度¶
4 记录¶
4.1 JaCoCo Commands¶
How to use kotsuite agent and jacoco agent to generate test case coverage?
# Collect code coverage information to exec file using kotsuite and jacoco agent
java \
-javaagent:"./kotsuite-agent/build/libs/kotsuite-agent-1.0-SNAPSHOT.jar=com.example.myapplication.TempCalleePrintHelloRound0.test_printHello_1" \
-javaagent:"./libs/org.jacoco.agent-0.8.10-rumtime.jar=includes=*,destfile=./output/jacoco-coverage.exec,output=file" \
-cp "example-projects/MyApplication/app/sootOutput/:libs/*" \
KotMain
# Analyze exec file to generate HTML report
java -jar libs/org.jacoco.cli-0.8.10-nodeps.jar report output/jacoco-coverage.exec --classfile="./example-projects/MyApplication/app/sootOutput/" --sourcefile="./example-projects/MyApplication/app/src/main/java" --html output/report
4.2 Soot¶
PrimType
5 测试 Android 项目¶
待测类:50 个
graph LR
class1[587] --!anonymous--> class2[107]
class2 --!private--> class3[106]
class3 --!abstract/!interface--> class4[97]
class4 --!data--> class5[65]
class5 --"has method"-->class6[45]
待测函数:239 个
6 其它测试生成工具¶
7 问题¶
- 构造函数问题:无法构造待测类的对象
- 总共的
public方法有 2396 个,大部分方法都是与 Android 相关(所在类是 Android 平台类的父类或函数参数为 Android 平台类)。- 去除 Android 相关方法和数据类后,只剩下 248 个待测方法,其中的 205 个为
Config类中的get(),set()方法,18 个为数据类(未被成功过滤)中的get(),set()方法。 - 剩余方法为 25 个。
- 去除 Android 相关方法和数据类后,只剩下 248 个待测方法,其中的 205 个为
- 因此必须考虑 Android 相关类的测试生成。
- 其他测试生成工具如何测试生成?
- 人工如何编写测试用例?
7.1 Android 相关方法测试用例生成¶
问题:无法直接使用构造函数构造对象
8 参考链接¶
- Android: Instrumented tests documentation
- Android: Activity testing
- Kotest
- Espresso
- Android: testing-samples
9 测试生成算法思考¶
需求:
- 针对什么生成测试用例?每一个
public方法?那override方法和生命周期函数要不要生成? - 生成什么样的测试用例?
- 如何生成?
activity如何获取?- 状态如何改变?
- 状态不是有方法序列改变,而是由动作改变,且不是所有方法序列都是合理地
- 而目前遗传算法中的个体是方法序列,需要改为动作序列吗?
思路:existing tools -> test script → unit test
问题:
- 传统的针对每一个
public生成测试用例的思路不可行 - 遗传算法针对方法调用序列以修改状态的方式不可行,因为有大量的方法都是父类的方法,且不可被直接调用
activity如何获取?什么时候需要 mock?如何 mock?
解决方案:
- Unit Test:只有少数的方法需要,采用传统思路
- Android Test:大部分,采用新思路
进度:
- 一期只做 unit test 部分
- 后面再做 android test 部分
下一步:
- 了解人工编写的 android test 长什么样,再来确定算法
- 做一次汇报
10 断言生成算法¶
局限性:只支持基本数据类型
思路一
- 生成正常的 jasmin class;
- 使用 java agent 做插桩,收集待测方法返回值;
- 使用 Socket 将返回值传给算法。(优点:可扩展性更高,可以收集其他运行时信息)
- 或 添加
println语句,通过outputStream的方式传给算法。
思路二
- 转换为 jimple 时,将最后一条语句的结果
print出来; - 收集 fitness 时,通过
outputStream的方式获取返回结果。
11 近期问题¶
- Android Test 的测试目标是 UI 测试吗?即每个测试用例是否对应一个用户动作序列?
- 测试用例集要针对哪些方法计算圈复杂度覆盖率?Override 方法(生命周期方法)是否考虑在内?
- 生成的测试用例集的圈复杂度覆盖率是用什么工具评估的?如 JaCoCo 等。
- Android Test 是不是需要针对每一个 public 方法生成测试用例集?如果是,那么是否需要对 Override 方法生成测试用例集?
回复
- 他们是想表达单元测试,是不在意 UI 测试的,他们是管理整个测试环节,所以很多细节他们没掌握。但实际场景中,确实是有涉及 UI 的很多。我也说了Activity 的测试生成问题。我让他们发内部写好的带有 Activity 的单元测试用例给你。这样我们能够容易考虑命令行和 android test的测试用例差异。
- 对针对public的方法写单元测试。对于override,方法A复写方法B,只测方法A。
- 他们用的Sonar计算圈复杂度,我印象中Sonar就是用的Jacoco的实现,你可以核对一下。







