目前,我的研究兴趣集中于高效的软件测试方法和软件测试理论。对软件进行测试,是保障软件正确性的关键手段,甚至是现实世界中唯一的可行手段。当然,大神Dijkstra说过:软件测试只能说明bug的存在,并不能说明bug不存在。从这个层面来说,是的,形式化方法、静态分析方法会更加完备(Complete)
很多人都会觉得“软件测试,不就是写写test case,有什么难的?”。然而,它只是看起来简单而已——上手容易并不意味着成为一个“高端玩家”就容易了。我们组目前想做的,就是成为这个领域的高端玩家
从我的角度出发,我觉得软件测试领域有几个核心问题:
覆盖(coverage)准则设计
覆盖准则关心的是,到底要测什么,测到什么程度?基础准则主要有基本语句块覆盖、路径覆盖、输入边界值覆盖等。但是,对于深度神经网络这种的基于数据训练出来的程序,这些基础准则就完全失效了
测试用例采样(sampling)
测试用例采样关心如何生成满足某种准则的测试用例集。最为常见的就是随机算法,比方说模糊测试(Fuzzing),其在编译器等安全攸关的软件上简直是神器。然而在某些具体问题上,随机算法会出现低效的问题,比如程序的某条路径难以达到(路径的约束可满足解占比全空间小)。换句话说,生成满足目标条件的测试用例集是个小概率事件时,随机方法就是难以满足要求。这时候设计更加高效的采样方法就是唯一可行的做法。我们组目前对采样算法有众多研究,包括自适应算法(动态调整采样策略)
测试用例采样关心的另一个问题是,有没有符合要求的最小的测试样例集大小?如果有,大概多大?如果要从理论上给出一个答案,那么这个问题是非常困难的。比方说,对于我们研究的组合覆盖(Combinatorial Coverage)而言,给出最小的采样大小是一个NP-hard的问题。而当软件的参数之间存在约束情况下
结果与分析
执行一条测试用例之后,我们就要对产生的结果进行分析。
判断结果对错
为了知道程序的运行结果是否正确,我们首先要对结果做判断:简单的错误,如崩溃(Crash)、断言违背(Assertion Violation)是可以高度自动化的。但对于复杂的功能性错误,如果我们不能很好的判断,那么测试就毫无意义
为了解决测试的Oracle问题,我们研究了蜕变测试(Metamorphic Testing)在纯组合测试中的应用
分析结果
当我们能判断结果的对错之后,就要对结果进行分析了。程序中的哪个元素或输入中的哪个片段是测试用例发现故障的罪魁祸首?这就是故障定位问题(Fault Localization)
在未来的研究,除了纯软件测试的工作,我们还打算做一些更有意思的工作,比如AI+CT(Combinatorial Testing,组合测试)