人们借助于测试用例的媒介作用,对程序的逻辑和功能提出各种疑问,结合问题开展热烈的讨论和争议,能够发现更多的问题。
6. 调试(Debug,排错)
软件测试也是一个系统工程,在做测试时,需要先做测试计划和规格说明,然后设计测试用例,定义策略,最后将测试结果与预先给出的期望结果进行比较,再做评价分析。而软件调试则是在进行了成功的测试之后才开始的工作。它与软件测试不同,软件测试的目的是尽可能多地发现软件中的错误,但进一步诊断和改正程序中潜在的错误,则是调试的任务。
调试活动由两部分组成:
① 确定程序中可疑错误的确切性质和位置。
② 对程序(设计,编码)进行修改,排除这个错误。
通常,调试工作是一个具有很强技巧性的工作。一个软件工程人员在分析测试结果的时候会发现,软件运行失效或出现问题,往往只是潜在错误的外部表现,而外部表现与内在原因之间常常没有明显的联系。如果要找出真正的原因,排除潜在的错误,不是一件易事。因此可以说,调试是通过现象,找出原因的一个思维分析的过程。
6.1调试的步骤
① 从错误的外部表现形式入手,确定程序中出错位置;
② 研究有关部分的程序,找出错误的内在原因;
③ 修改设计和代码,以排除这个错误;
④ 重复进行暴露了这个错误的原始测试或某些有关测试,以确认该错误是否被排除;是否引进了新的错误。
⑤ 如果所做的修正无效,则撤销这次改动,重复上述过程,直到找到一个有效的解决办法为止。
从技术角度来看,查找错误的难度在于:
现象与原因所处的位置可能相距甚远。就是说,现象可能出现在程序的一个部位,而原因可能在离此很远的另一个位置。高耦合的程序结构中这种情况更为明显。
当纠正其它错误时,这一错误所表现出的现象可能会暂时消失,但并未实际排除。
现象实际上是由一些非错误原因(例如,舍入得不精确)引起的。
现象可能是由于一些不容易发现的人为错误引起的。
错误是由于时序问题引起的,与处理过程无关。
现像是由于难于精确再现的输入状态(例如,实时应用中输入顺序不确定)引起。
现象可能是周期出现的。在软、硬件结合的嵌入式系统中常常遇到。
6.2几种主要的调试方法
调试的关键在于推断程序内部的错误位置及原因。为此,可以采用以下方法:
① 强行排错
这是目前使用较多,效率较低的调试方法。它不需要过多的思考,比较省脑筋。例如:
通过内存全部打印来排错(Memory Dump);
在程序特定部位设置打印语句;
自动调试工具。
可供利用的典型的语言功能有:打印出语句执行的追踪信息,追踪子程序调用,以及指定变量的变化情况。自动调试工具的功能是:设置断点,当程序执行到某个特定的语句或某个特定的变量值改变时,程序暂停执行。程序员可在终端上观察程序此时的状态。
应用以上任一种方法之前,都应当对错误的征兆进行全面彻底的分析,得出对出错位置及错误性质的推测,再使用一种适当的排错方法来检验推测的正确性。
② 回溯法排错
这是在小程序中常用的一种有效的排错方法。一旦发现了错误,人们先分析错误征兆,确定最先发现“症状”的位置。然后,人工沿程序的控制流程,向回追踪源程序代码,直到找到错误根源或确定错误产生的范围。
回溯法对于小程序很有效,往往能把错误范围缩小到程序中的一小段代码;仔细分析这段代码不难确定出错的准确位置。但对于大程序,由于回溯的路径数目较多,回溯会变得很困难。
③ 归纳法排错
归纳法是一种从特殊推断一般的系统化思考方法。归纳法排错的基本思想是:从一些线索(错误征兆)着手,通过分析它们之间的关系来找出错误。
归纳法排错步骤大致分为以下四步:
收集有关的资料 :列出所有已知的测试用例和程序执行结果。看哪些输入数据的运行结果是正确的,哪些输入数据的运行结果有错误存在。
组织数据 :由于归纳法是从特殊到一般的推断过程,所以需要组织整理数据,以便发现规律。常用的构造线索的技术是“分类法”。
原文转自:http://www.uml.org.cn/Test/201511262.asp