本文内容包括:
本文来自于 Rational Edge:通常所说的“累积测试分析(Cumulative Test
Analysis)”技术向软件测试团队提供了对自动化测试更合理的方法,特别是在回归测试集的领域内。理解 CTA 如何提高您的测试效率。
您的测试团队已经非常成功了。您已经对自动化大量投资,并且因生成大型且全面的测试集而著称 —— 您可以无可非议地为之自豪!在整个开发过程和多个环境中,这些组合为您很好地服务。因此现在是您休息一会,并且收获您所劳动的好处的时候了,对吗?或者,您将成为您自己的自动化测试集的牺牲品?
也许,像许多团队一样,您已经达到饱和点,现在您有太多的测试,以至于不能说明。也许运行测试的团队已经不再是撰写它们的团队了,并且知识是稀少的。或者也许您受困于对大量所支持的环境和代码流不断地重复运行同样的测试的工作。对于那些您不能运行的测试,或者您没有时间运行的,您对您所带来的风险进行过观察吗?
无疑地,如果您只运行少量的测试,并且仍旧在代码中找到一样的缺陷,这是更好的。通过运行可能的测试尽可能快地找到第一次出现的缺陷不同样是更好的吗?
不能达到的目标
甚至是出于一片好心,每个测试人员在他或她的工作生涯中,都将撰写一个根本不测试所打算测试内容的测试。这可能是由于缺乏经验,对产品功能设计的变更,因为测试人员做出关于产品或其预期使用价值的无效假设,或者只是因为测试人员用尽了时间。总而言之,最终结果是由于与产品缺陷不相关的原因而失败的测试。
这些失败测试的累积效应创造了回归套件中的灰色区域,您的回归测试的 5% 到 15%是困难的、不可靠的或不可能成功地运行完成的。这些阻塞的或不可靠的测试消耗了宝贵的测试时间,并且混淆了测试人员对真实的产品缺陷的观察,这导致了在回归测试循环末尾的测试进度中的指数的缩小。虚幻的所有可用测试的100%
的运行目标常常看起来非常接近,但是却难以达到。
自动化陷阱
也许您已经落入了严重依赖于您的测试自动化基础架构的陷阱了。这里有一些您可能考虑的问题。您是:
- 缺少用于测试您所期望的每样东西的资源吗?
- 陷入无休止的测试循环吗?
- 在没有找到任何新的缺陷的情况下,运行成千上万的测试吗?
- 在不了解那些测试的价值的情况下,花费您大部分的时间来确定坏掉的测试吗?
- 瞄准 100% 运行您所有的测试的目标吗?在质量和风险方面您了解此目标吗?
您可能需要的是,不再瞄准任意数量的测试,而着眼于从上次测试以来在产品中实际变更的功能是什么,以及测试此变更所需要的是什么。总而言之,您需要转移到更深思熟虑的“目标”测试的方法。
停止运行测试,开始寻找缺陷
通常所说的累积测试分析(Cumulative Test Analysis,CTA)方法是基于五个基本原则的:
- 定期地运行自动化的测试。
- 了解现有测试材料的实际覆盖和质量。
- 运行尽可能少的测试。将测试关注在只运行那些覆盖了发生变更的功能的测试。
- 在做出评估时考虑所有的测试活动。
- 由四个较早的步骤所节省下来的时间可以用于增加测试套件的质量,或者执行额外的测试。
让我们按顺序讨论这些原则。
原则 1:定期地运行自动化的测试
CTA 方法着重于通过在整个的开发循环中运行自动化的测试将“发生缺陷的时间” 1 最小化。任何回归类型的缺陷都可以很早发现,并且与在循环的末尾运行单个的长期回归运行相比使用了最小量的测试。
此测试的目标是提供对所有驱动程序的功能质量的一个观察,作为进一步测试和最终向市场发布的基础。此回归测试减少了进入最终产品的缺陷数量,以及在这期间,减少可能防止新特性的更复杂的测试的基础功能问题。由此可见,这些回归类型的缺陷需要在其最方便确定的时候尽可能快速地清理掉。
原则 2:了解回归测试套件中现有测试材料的质量和覆盖
如早先讨论的,包含于回归套件中的许多测试在任何规模的测试操作中可能不能生成可靠的结果。为了完全了解产品的质量,事实上,根据潜在的产品缺陷,您在观察的结果意味着什么,您必须首先了解测试实际上测试的功能是什么。
为此,我们求助于代码覆盖的使用。对于外行来说,这实际上是所有方法、类和测试从开始到结束所经过的代码途径的细微痕迹。这种在一个测试接一个测试的基础上的运行时度量提供了对测试做什么的观察,并且比起在实际的测试运行过程中的运行时收集信息时依赖于测试计划或测试文档来说,是一种了解要测什么内容的更精练的方法。当然,对于此途径存在着由,例如,寻找缺陷并执行异常路径的测试引起的偏差。总的来说,尽管,如果代码覆盖数据是在成功的测试运行过程中收集的,那么此信息可以存储起来随后作为测试的功能的指示。
有许多可用的工具可以提供代码覆盖率。它们都典型地使用被测代码的某种形式的装置,这将钩子(hooks
)加入了产品代码中。当测试材料遇到这些钩子时,代码覆盖工具使用这些钩子来记录每个测试在其执行时所经历的过程。最终结果是一个表示与特定的产品驱动程序冲撞的所有测试的完全覆盖的数据库。因为回归测试材料随着时间的推移变化得不大,那么此数据仍旧相对静态。然而,如果产品或测试材料随着时间的推移变化很大,那么就需要重复实施装置。
原则 3:尽可能少地运行:关注于您的测试
该标题可以等同于这样措辞,“不要浪费时间运行您与先前的驱动程序冲撞的测试,除非它们测试的功能已经变更了。”减少测试运行的数量可能对那些使用回归套件作为获取回归安全网的许多团队来说需要信仰上的飞跃,但是这种飞跃将节省数不尽的不必要的回归测试时间。
实际上,实现确定目标的测试需要两件事:1)了解在测的产品驱动程序中确切变更了什么,以及 2)了解您的测试材料(如前面部分中讨论的)。
上面中的第一个在产品代码处于某种库控制形式时相对容易获得。库系统,例如 CMVC、CVS 或
Rational ClearCase 提供创建逻辑变更或截然不同的层次集合的机制。对于这些层次,个别的工具能够提供某种粒度上的一系列变更,不论是文件、包、类或某些更细粒度的类别。有了这两项信息,确定将在最少的时间内,达到变更功能的最大代码或路径覆盖的现有测试记录的子集是可能的。
如果没什么发生变更 —— 或者,更可能的是,您没有对发生变更的功能进行测试 —— 您只是不运行任何东西!这样做是对您可以花费在其他地方的宝贵时间的浪费。
此处给出一个警告:如果回归测试套件是范围非常广泛的,那么这将有极好的效果。但如果覆盖很低,那么有时候,目标测试可能使您得出结论,您没有合适的测试值得运行。记住,在这一点上,用回归测试的标准方法,团队会盲目地运行整个回归套件。这几乎不会增加价值,但确实会花费很多时间。通过使用
CTA 方法,您可以利用节省的时间来撰写新测试增加您的覆盖率(参见在下面的原则 5 中的讨论)。
累积观点:沿用先前的测试结果
除了确定测试目标,CTA 还利用另一个关键的概念减少了所需的测试运行的数量:累积的结果分析。一旦确定了测试的目标是只覆盖变更的功能,那么来自于未变更代码区域的结果就可能从一次构建转移到下一次。
此方法的重要好处是允许使用最少的测试数据进行质量评估。这对于发布循环的末期是特别有用的,此时要做出少量的变更,并且大范围的运行测试会过高地耗费时间。最终的决策可以根据实际上许多星期或月之前的测试数据做出,而产品仍旧保持一段时间的功能稳定。
通过将目标测试和累积结果分析两条原则组合起来,在测试循环早期运行的测试可能不再需要再次运行了,它们的结果将保留到最后。类似地,任何覆盖不稳定的代码区域的测试可能需要每天都重新运行。通过采用此方法,可以将测试着重于产品的那些携带最高风险缺陷的区域。
实例:传统测试与目标测试
下面的一系列图表显示了一个来自于典型的回归测试执行的可能输出的人为实例。我们首先使用传统方法,然后对这个系列的构建使用目标方法,以及累积结果分析。
考虑下面图 1 中显示的场景,这可能是导致输出一般利用率(GA)的开发循环的一部分。测试团队已经利用了由构建
3 和构建 11 获得的最重要的结果数字对连续的构建尝试许多回归执行。
图 1:每次构建的测试完成百分比,使用传统的回归测试方法
利用传统的分析方法并研究图 1 中的图表,我们只能得出以下有限的结论:
- 没有一次回归达到 100% 完成 —— 不可能说出余下的测试对整个质量陈述是否重要。
- 很可能的是对构建 4 到 8 的小百分比的测试,要么为测试的确定重新运行,要么新的测试是覆盖没有为构建
4 的额外功能 —— 不论发生哪种情况,都不可能在不进一步分析的情况下确定地知道。
- 此图表中不清楚的是为什么对构建 9 执行如此多的测试。
不可能从图 1 中的得知的是,回归套件中的所有测试是否在某一处都运行了。对此,我们求助于图
2 中显示的图表。
图 2:利用传统回归测试方法的累积测试完成百分比。
图 2 显示了对构建 11 收集的一段时间的测试的累积结果。此处,很可能看到的是团队计划运行大部分可用的测试,并且发现许多测试失败,然而,运行这些测试所花费的时间意味着在产品发布的时候这些中的许多仍旧存在。
让我们为该虚拟场景填充一些背后细节。设想构建 3 是最初的 GA 候选,差不多 80% 的可用测试生成了好的结果。其间,缺陷确定和其他变更慢慢地进入到由于工作都集中于构建
3 而很少测试到的后继构建中。构建 9 宣布为新的 GA 候选,并且测试再次开始。当构建 11 成为最终的 GA 构建时,测试工作再次重新开始。如在图
2 中可以看到的,此次对构建的测试直到 GA 驱动程序生成之后 11 天才能完成。
累积测试分析的情况
现在,让我们将图 1 和 2 中例举的传统方法与新方法在同样的情况下进行对比。首先,我们对来自于上面测试的结果执行累积测试分析的新技术。为了这样做,我们向此图表引入许多附加颜色(参见图
3)。
如以前一样,通过(绿色)或失败(红色)的新测试显示为暗色。因为图 3 显示了测试循环的末尾,所以显示出很少“新的”测试运行。
用橙色突出的测试表示那些瞄准已知构建,但因某种原因没运行的分析。
浅绿和浅红色的结果表示从较早的构建中转过来的结果。“新的”和“重新运行”的测试之间的差别仅仅是,“新的”测试是那些对正讨论的构建首次运行的测试。
还要注意的是图表不再从 0% 到 100%,而替换为测试的度量数字。这背后的原因将在我们讨论新数据时显现出来。
图 3:利用传统回归测试方法的 CTA 累积测试结果
利用该技术,我们立即有了更多要考虑的信息:
- 橙色“遗漏”结果表明构建 1 和 2 没有充分的测试,但它们从对早期的构建的测试(没有显示)那里带来了非常多有效的结果。
- 对构建 3 的测试减少到遗漏测试累积的大约三分之二,所需的余下的测试在整个过程中都没运行,直到构建
11。
- 附加的测试针对于构建 6(“遗漏”测试的数量增加),说明对产品有附加的功能变更。
- 对许多构建出现了大量的测试,构建 3、构建 9 和构建 11 特别的昂贵 —— 问题是,这些都是必要的吗?
接下来,因为知道变更是 CTA 的重要部分,所以我们引入一个图 4 中的新图表,显示出每次构建中变更的影响,以及那些变更测试得有多好。数据重新从构建带到相关的构建中,被变更了的类被反映在零线以上,而覆盖这些变更的测试在零线以下。充分测试的变更将因此显示为一个绿色的条,处于与上面所示的变更相同高度的轴之下。
图 4:每此构建的变更以及所完成的测试
通过传统的回归测试的观点查看该数据,可以看到,对构建 3 的测试是有效的,但是构建 4 到 8
中对产品类的附加的功能变更(显示为“新的”或者“非常新的”项),直到构建 11 才完全测试完成。上面较早描述的其它提示点:
- 构建 1 中出现的大量变更,并且几乎所有这些都对构建 3 充分测试了。
- 在构建 3 之后,许多未测试的变更从一个构建带到了下一个中,使“确定缺陷的时间”拉得更长。
- 在构建 4 和 5 中出现的大量变更,可能已经否定了早先执行的测试的某些好处。更重要的是,对构建
3 运行的并且随后不在循环中重新运行的测试可能会错过构建 4 或之后引入的缺陷。
- 我们管理了对每个构建运行的少量测试,我们将提供所引入变更的最有效的覆盖。
利用目标测试使效果最大化
指出了老方法中的不足,我们现在使用新的方法。假设相同的环境,通过 CTA 可以完成什么?要论证这点,如先前一样,我们使用同样的两个图表,图
5 和 6 中分别显示出结果和变更。
图 5:利用目标测试方法的 CTA 累积测试结果
图 5 和 6 中的数据是基于已经部署了累积测试分析和目标测试的测试团队,在需要覆盖每次构建中的变更时只运行那些确定出来的测试。
从此结果数据中看,第一件要注意的事情是采用了较少的测试 —— 实际上,相比使用传统方法的 3000
个,运行了大约 1700 个测试。这在图 5 中显示为较少的“新的”或“重新运行的”测试,这可以折合为相对短的时间间隔内的重要的时间节省。
图 5 和 3 中第二个明显的差别是构建 3 之后没有橙色的“遗漏”条了。在这种情况下,测试团队利用许多构建来测试构建
1 中引入的所有变更,而在很短的一段时间内,运行了所有确定的测试。即使有这一点延迟,确定缺陷的时间比传统方法减少了。更重要的是,在测试循环中出现的测试中,不再存在对最终构建质量上的观察的
11 天的延迟。这极大地降低了一个已被交付的未测试的变更风险。
图 6 中还说明了效率,这显示出更少量的从一次构建到下一次的未测试的或“带过来的”变更。通过在引入了缺陷的构建中找到这些缺陷,可以尽可能低成本地进行确定,并且减少了相互依赖的缺陷修复的复杂链的风险。对一次构建启动测试,并在随后的构建中偿还债务的方法,只要在后继的构建中相同的功能没有变更时都会有效。
最后的重点是相同的缺陷 —— 也就是,图 5 中的失败测试 —— 用新的和旧的方法都找到了。
图 6:利用目标测试方法,每个构建的变更和完成的测试
原则 4:考虑对所有构建执行的所有测试
CTA 的第四个基本原则依赖于这样的事实,每个对软件的测试都提供一个质量指数。该测试可能延伸到基本的产品安装、单元测试、简单的配置,或正式的
FVT 或 SVT 活动。类似的,如果在不同的环境中运行同样的或相似的测试(举例来说,在不同的操作系统上),那么结果应该包含于质量说明中。
此原则的一个扩展是这样一个事实,对一个没有变更的功能执行的测试可能仍旧认为是有效的。如图3 和
图5 中所示,允许收集累积的结果。同样的,如果新的区域内的后继测试提供了一个存在测试问题的指示,那么这也应该包含于质量评估中。因此在提供已知构建的质量投影的时候,工具考虑了所有测试。
原则 5:利用节省的时间来提高质量、撰写新的测试
利用 CTA 和目标测试意味着您不再有 100% 执行的目标了。确切地说,目标随着对产品做出的变更日复一日的改变。问题出来了:人们如何知道什么时候回归测试完成了?回答很简单:直到所有变更都停止了,并且覆盖所有的变更
—— 那些由分析过程所确定的 —— 的测试都运行了,测试才完成。在这一点上,团队利用回归套件几乎完成了每件可能的事情,以确保不会引入额外的缺陷。
注意我们说过“团队几乎做了每件事情”,因为方法将只瞄准那些已经包含于回归套件中的测试。如果因为出现了变更,当您没有对变更进行测试,那么您将会无法查看到您仍旧具有的风险。
使用此新方法,您可以确信的是,您已经运行了您现有的测试组合中可能的每个测试,来确保最低可能的风险。图
7 例举了这一点,基于每个变更类型中方法的唯一覆盖率,显示出测试套件和它们所覆盖的变更之间的关系。
图 7:测试套件和它们所覆盖的变更之间的关系
在图 7 中的实例中,组 S3、S4 和 S5 不唯一地覆盖 S1 和 S2 所覆盖的任何方法,然而,通过运行它们,团队可以确定它们可以运行触及部分变更的每一个测试。
最显著的是,橙色区域 —— 没有被绿色覆盖的部分 —— 在图中表示根本没有被回归套件中的测试覆盖到的变更。因此团队需要将他们工作的重点集中于撰写提供此覆盖的测试,为了完全测试变更并且将错过潜在缺陷的风险减少到其最低可能的值。幸运的是,CTA
方法给团队时间来开发这些所需的测试。
心理转变
这不是新技术或一种根本的新样式。背后的思想在最初设想代码覆盖时就出现了。技术提供的东西,尽管,从测试团队的观点来看是一组直觉上正确的思想,但这仍旧表示对许多内容强调的基本变化。只运行测试的子集去掉了“做一些有价值的事情”的兴奋感觉,这是运行整个回归套件的传统实践提供的感觉。该新方法还需要来自于项目管理团队对不再朝着基于风险的
100%的运行目标,而只对每次构建运行恰当的测试的了解和支持。这没有去掉将团队着重于调试测试失败或撰写新测试的需求,但这样做可以为做重要的工作赢得额外的时间!
注释
1 发现缺陷的时间(Time to defect):将缺陷引入到产品代码中和将缺陷报告分配给进行确定的开发人员期间经过的时间。 |