调试是执行一次成功的测试后所要进行的工作。调试包括两个步骤:第一步,确定程序中可疑错误的准确性质和位置。第二部,修改错误。
一、暴力法调试
特点:不需要过多思考,耗费脑力较少,效率低下
- 利用内存信息输出来调试
- 在程序中插入打印语句调试
- 使用自动化的调试工具进行调试(设置断点等)
这些问题如果应用在大型程序中,调试效率会非常低下,一般只作为备用方法。
二、归纳法调试
归纳法是线索(即错误症状或测试用例的结果)出发,寻找线索之间的联系。
使用归纳法调试的过程如下:
- 确定相关数据:列举所有知道的程序执行的正确和不正确之处。那些相似却不相同,有的引起症状有的未引起症状的测试用例会提供很多有价值的线索。
- 组织数据:组织相关数据,以便观察线索间的模式,尤其重要的是找到矛盾点。可以利用“是什么”、“在何处”、“多大程度”列表,从而对数据进行总结观察,做出假设。
- 做出假设:利用线索结构里可能的模式做出一个或者多个关于错误原因的假设。如果有多个假设存在,首先选择最有可能的一个。
- 证明假设:如果忽略这一步,接下来可能只能修正症状,而不能解决问题本身。所以应该将假设和最初的数据或线索进行比较,来证明假设的合理性,以确定这些假设完全可以解释这些线索的存在。如果无法解释,这些假设要么是不完整或无效的,要么还有更多错误的存在。
- 解决问题:解决问题后仍然需要做回归测试以确保问题和错误修复没有引入其他错误。
三、演绎法调试
演绎的过程是从一些普遍的理论或者前提触发,使用排除和精炼的过程,达到一个结论。过程如下:
- 列举所有可能的原因或假设:第一步是建立一份所有想象得到的错误线索的清单,线索不需要有完整的假设,可以纯粹是一些猜测。
- 利用数据排除可能的原因:详细检查所有的数据,尽量排除所有可能的原因。如果排除后,剩下的原因多余一条,选择最有可能的一条。
- 提炼剩下的假设:利用现有的线索提炼这个推测,即细节化、具体化。
- 证明剩下的假设:此步骤与归纳法中的第四步一样。
- 修复问题:此步骤与归纳法中的第五步一样。
四、回溯法调试
在小型程序中定位错误的一种有效方法是沿着程序的逻辑结构回溯不正确的结果,直至找到程序逻辑出错的位置。即从程序产生不正确结果的地方开始,逆向执行程序,重复使用“如果程序在此处的状态是这个样子的,那么在上面位置的状态就必然是那样的”的过程,很快就能定位出错误。
五、测试法调试
当发现了某个被怀疑的错误的症状之后,我们需要编写与原先有所变化的测试用例,尽量确定错误的位置。实际上,这个方法经常和归纳法或演绎法一起使用。
总结:所有的测试方法都有一个共同的方法,就是“思考”!修改错误时,要注意应该纠正错误本身,而不是其症状,并且应该意识到,改正错误会可能引入新错误。抱着严谨的态度去思考,才能向着精确和高效的道路上迈进。