现代社会离不开计算机。计算机做许多事情。人们上网购物。人们用手机聊天。工厂机器自动运转。这些背后有软件控制。软件由人编写。编写软件需要技术。我的毕业论文研究一种软件技术。这种技术让软件更可靠。可靠就是少出错。出错可能造成损失。银行系统出错很麻烦。医疗设备出错很危险。汽车控制系统出错更严重。所以软件必须可靠。
软件由代码组成。代码是一行行指令。计算机执行这些指令。代码可能隐藏问题。问题也叫缺陷。缺陷导致软件行为异常。发现缺陷很重要。发现缺陷需要测试。测试就像检查。测试人员用各种方法检查软件。一种方法是运行软件。输入一些数据。看输出对不对。如果不对就找到了缺陷。测试很花时间。大型软件代码很多。人工测试很慢。于是人们用工具帮助测试。
我的研究关于自动生成测试用例。测试用例是一组输入和预期输出。它用来检查软件功能。生成测试用例可以用很多方法。我研究其中一种方法。这种方法模仿自然进化。进化是生物界的现象。生物通过繁殖产生后代。后代特征来自父母。有的后代更适应环境。它们更容易生存。一代一代这样进行。群体整体变得更强。这种方法用在测试上。我们把测试用例看作生物个体。每个测试用例有一些特征。特征就是输入数据。我们定义怎么算适应环境。适应就是能发现软件缺陷。能发现缺陷的测试用例更好。
首先需要一群初始测试用例。初始群体可以随机生成。随机生成就是随便造一些数据。这些数据可能没什么用。但没关系。进化过程会改进它们。我们需要一个评价标准。评价标准叫适应度函数。适应度函数给每个测试用例打分。分数高表示测试用例好。分数怎么定呢?要看测试目标。常见目标是覆盖更多代码。覆盖代码就是执行了代码的哪些部分。执行过的代码我们标记它。没执行的代码可能隐藏缺陷。所以让测试用例多执行代码是个好目标。
适应度函数根据代码覆盖情况打分。执行了新代码的测试用例得分高。得分高的测试用例被选中。它们成为父代。父代产生子代。产生子代用交叉和变异操作。交叉像混合。两个父代测试用例交换部分特征。产生两个新的测试用例。变异像微小改动。一个测试用例的某个特征随机变化。变成一个新测试用例。子代和父代组成新群体。新群体继续评价和选择。这个过程重复很多次。这就是进化。
进化过程可能找到好的测试用例。好的测试用例覆盖了难覆盖的代码。难覆盖的代码可能是复杂逻辑。复杂逻辑有很多条件。条件组合很多。一般测试不容易执行到。进化测试能慢慢接近这些条件。通过一代代改变输入数据。最终让软件执行到那些深层代码。执行到了就可能发现缺陷。缺陷可能是条件判断写错了。或者计算公式错了。发现缺陷后程序员可以修复。
我的研究具体改进进化方法。传统进化方法有时效率不高。它可能花很多时间却进步很慢。我分析问题在哪里。问题可能是适应度函数不够好。分数不能准确反映测试用例的优劣。于是我设计新的适应度函数。新函数考虑更多因素。不仅考虑是否执行了新代码。还考虑执行了哪些代码。有些代码更重要。比如错误处理代码。错误处理代码平时不容易执行到。但一旦执行到可能发现问题。我让适应度函数给这类代码更高权重。权重就是重要性系数。重要性系数高的代码覆盖后得分更高。这样进化过程会更努力覆盖这些代码。
我还改进了交叉和变异操作。传统操作是盲目混合和随机变化。我加入一些引导。引导就是利用已有信息。比如哪些输入值容易触发重要代码。这些信息来自程序分析。程序分析是静态检查代码。不运行软件只看代码结构。分析出代码里的条件依赖。条件依赖就是输入和条件判断的关系。知道关系后可以指导交叉和变异。让变化更有方向。方向明确进化就更快。
我做了实验验证我的方法。实验需要一些实际软件作为对象。我找了一些开源的软件项目。开源就是代码公开。这些项目有不同大小。有的几百行代码。有的几万行代码。我在这些项目上应用我的方法。同时用传统方法做对比。对比看哪个方法更快找到缺陷。缺陷是已知的。这些开源项目有历史记录。记录里标记了已经发现的缺陷。我们把这些缺陷故意放回代码。放回就是恢复缺陷版本。然后看测试方法能不能发现它们。发现意味着测试用例触发了缺陷。触发后软件行为异常。我们记录异常就算发现。
实验过程用计算机自动运行。每个方法运行多次。记录每次发现缺陷的时间。时间以进化代数计算。也以实际计算时间计算。实验结果用数字表示。数字显示平均情况。我的方法在大多数项目上更快。更快意味着用更少的代数发现缺陷。也意味着实际时间更短。时间短就是效率高。效率高对实践有帮助。企业开发软件可以节省测试时间。节省时间就是节省成本。成本降低有经济意义。
我的方法也有局限。局限体现在某些特定软件上。比如软件代码结构很特殊。特殊结构让程序分析困难。分析困难导致引导信息不准。信息不准可能降低效果。效果降低就需要调整方法。调整可能需要人工干预。人工干预增加了使用难度。难度高不利于推广。这是未来可以改进的地方。未来研究可以加强程序分析能力。或者设计更通用的引导策略。策略通用就不依赖具体软件结构。
软件技术不断发展。新编程语言出现。新编程范式出现。测试技术也要跟上。进化测试是众多测试技术的一种。它适合复杂软件。复杂软件逻辑路径多。人工设计测试用例困难。自动生成有价值。我的工作让自动生成更有效一点。有效一点也是进步。进步积累起来就推动领域发展。发展最终让软件质量更高。高质量软件让人们生活更便利。便利生活是技术研究的最终目的。
研究过程需要很多知识。我需要学习进化算法原理。需要学习软件测试基础。需要学习程序分析技术。需要学习实验设计方法。学习通过看书和论文。也通过编程实践。编程实现我的想法。实现过程遇到很多问题。问题要一个一个解决。解决不了就找老师讨论。老师给出建议。建议启发我找到新思路。研究是漫长过程。漫长过程需要耐心。耐心帮助我最终完成工作。完成工作让我对技术理解更深。理解深对未来工作有帮助。我可能继续做研究。也可能去企业开发软件。无论哪条路,这段经历都有用。有用在于学会了如何解决难题。难题在生活中处处存在。解决难题的能力很重要。这就是我的毕业论文研究技术相关的内容。