认定测试(Approval Testing)是一种测试技术,它比对代码的当前输出和“已认可”的版本。最初检查测试输出时,若对认可结果即则会形成这个所谓“已认可”的版本。当需求变更时,你可以重新审视这个已认可的版本并轻易更新它。TextTest 已支持认定测试,这是一款开源工具,用于基于文本的功能性测试。
Emily Bache 是一名培训师、软件开发人员和架构师,在欧洲测试大会2017 上召开了一个研讨会,主题为使用TextTest 进行认定测试。InfoQ 通过问答、总结和文章的方式全程报道了此次会议。
Bache 首先解释了基于认可的测试的概念,以此作为研讨会的开场白。她展示了如何在 TextTest 中建立测试,然后首次运行它去产生输出数据。
该研讨会的参会者实践了使用 TextTest 进行基于认可的测试,定义了新的测试用例并运行了它们。在首次运行一个测试时,如果认为程序运转正确,则会生成一个输出,再次运行时会检查这个输出,如果输出没问题,那么它们就会对它进行审核,把测试标记为“通过”。
如果输出有问题,那么他们就发现了缺陷。那么这个输出就不是被认可的,测试人员可以把它指出来或在这个输出里为开发人员加条备注,待修复之后再审核它,Bache 说。因为本次产生的输出与之前已认可的输出不同,所以 TextTest 将把该测试标记为“失败”。如果程序更新了,缺陷消除了,那么这个测试会被再次运行,并将通过。
InfoQ 有幸就认定测试技术采访了 Emily Bache,并请她谈了谈如何使用 TextTest 来做认定测试。
InfoQ:什么是认定测试?
Emily Bache: 其基本理念是,通过比较代码的当前输出与之前运行的测试所形成的“已认可”的版本,来决定测试是否通过。
所以你首次运行一个新的测试时,没有任何可用来比对的已认可版本。你也许大致知道预期的结果,也许你脑中有个大概,或者用户故事交流中的一些笔记让你记得应出现什么情况。你手工检查代码的输出,决定它是不是足够好了。如果你不确定,可以做些计算,或者把它展示给专家级的用户。一旦你做出决定,认为该行为值得保留下来,将“认可”该输出并把它保存起来。然后所有后续测试将比对实际结果与这个已认可的版本。通常,你可以使用简单的文本比较工具来做这种比对,任何差异都认为这个测试是失败的。
如果你看过一些像“扫地雷(Minesweeper)”这样的编码套路,问题在于 ascii 码形式的输入(地雷的范围区域)和预期输出(同一范围区域,但还有地雷和邻近的地雷数)。使用基于认定的测试就能很好地完成这个工作,因为每个测试用例比较一个输出雷区和已认可的输出方案。当测试失败时,差异通常能清楚地展示出什么出错了。其实,我们已经把它做进了一个认定测试小练习中了,并把它公开发布到了 github 上: Minesweeper Approval Kata 。
你可以设计一些新的雷区(也许是真正偏僻的问题?)并把它们放入认定测试中。我已经完成了一些与 Yatzy 和 Gilded Rose 套路很类似的事,以展示即使输出不是图形化的,此方法同样有效。
InfoQ:认定测试与基于断言的测试有怎样的不同?
Bache: 在“基于断言”的测试中,你必须选择输出的一个方面进行检查,然后写特定的代码去检查它。我们经常讨论这种测试所具有三个部分:准备、执行、断言。在认定测试中,前两部分是一样的,而第三部分有所不同。测试设计人员仍决定要测试什么场景,以及如何去触发该场景,但不预先定义将输出什么,至少不含任何细节。一旦你有了测试的前两部分,就可以开始执行并评估输出了。如果输出不够完备或比较粗略,你可以继续维护产品代码,直至输出值得保留为止。当你对它足够满意时就可以“认可”这个结果并把测试分享给团队,而没必要等到故事末期。这种测试具有天然的“敏捷性”,当需求变更时,你可以重新审视这个已认可的版本并轻易更新它。
InfoQ:你在认定测试中是如何使用 TextTest 的?
Bache: TextTest 是一个开源工具,我和其他一些人现在已经使用它很多年了。它初衷设计为语言无关的,它的测试处于可执行程序层,而不是单独的函数或类上。例如,我已经用它测试过用Java、Scala、C++、Python 和 Ruby 的程序了。
不仅可以测试整个程序,TextTest 还会完成纯文本输出的比对。当然,并非所有程序的正常功能的输出都是纯文本的,但大多数输出物都可以转换为纯文本。例如,PDF 或 HTML 文件就能转换为纯文本,复杂的用户界面可以描绘成 ascii 形式,数据库可以查询输出为纯文本报表。以我的经验来看,为你的应用创建一个做此类转换的测试工具是值得的,它将在许多测试用例中得到复用。如果你的测试主要由纯文本内容的文件目录结构构成,就有很多可以自由使用的工具了,搜索、比对、正则表达式和版本控制等等。
InfoQ:什么时候做认定测试,又有哪些收益呢?
Bache:我通常把认定测试用于端对端的测试或 API 测试,在这种情况下你想要确认的是整个特性按用户预期工作。我认为它很自然地遵循了“认可”输出的需要,你希望测试所围绕的基础是用户或领域专家能够阅读和理解的东西。如果你能在他们熟悉的工具(比如 PDF 文档、网页或用户界面截图)中为他们展示测试结果,那么他们可能更相信测试正在检查的是他们关注的东西。基于断言的测试通常对于他们来说太难理解了。
基于断言还有个弊端是针对每个新测试用例都要写新的断言代码。如果你使用认定测试,则可以经常复用为之前的测试用例所写的测试工具。我认为总体上维护的代码要更少一些。
我经常在遗留代码上使用这种方式,这些是仍会被使用的代码,但缺少测试覆盖,难以保证在不被破坏的情况下对其进行变更。仅仅触发不同的场景并认定这些程序的所有输出都是正确的,你就能快速获得一套适当的回归测试了。
这些都是好的方面,但认定测试的“杀手级特性”是能够找到设计测试时未预期到的缺陷。若使用基于断言的测试,你就得明确判定输出有哪些方面要予以检查。你断言,这个左上角的正方形紧邻着两颗地雷。这张发票显示应付数额、银行存款数额和客户编号。但是,如果雷区漏掉最后一列会怎么样呢?或者账单包括的是账单跟踪信息而不是投递地址呢?你会记得去为它们写断言吗?
默认情况下,认定测试将比对整个输出,以我的经验来看,这是个发现这类问题的好机会。实际上,输出中有的内容是你不想检查的,这种情况经常发生。你可能显示了今天的日期、流程编号或随机数,这些东西随时都会变,在与已认可的版本进行比对前需要先过滤掉它们。但是,测试设计人员的角色发生了转变,不再是选择哪些东西要断言,而是选择哪些东西要忽略。总而言之,你有更多的可能发现这些意料之外的变化,免得被它们弄得顾此失彼。
InfoQ:如果测试人员想要了解认定测试的更多内容,可以去哪里呢?
Bache:好的,首先我不认为这是一项仅针适用于测试人员的技术。我认为所有开发人员在对他们代码进行测试时都能得到收益,在开发新功能的时候,你可以运用此技术以测试驱动的方式开展工作。我的经验表明,如果开发人员、测试人员和专家级用户或产品负责人能在一起做这个测试套件,会从中得到更多的收益。
我认为学习一项新技术的绝佳方式是在你已经熟悉的问题上进行尝试。如果你之前曾研究过扫地雷、骰子游戏或镀金玫瑰编程套路,建议你在我的 github 页面上看一下它们的认定测试版本: Yatzy Approval Kata 、 GildedRose Approval Kata 。只要你去了,就能用我的每个“示例解决方案”来比对你的测试了。我计划增加更多的练习,如果你有特别喜欢的编程套路想要看到以此方式解决的话,请写信给我。
如果你喜欢了解这个方法的背景、具体经验和理论依据的话,有许多相关的文章甚至科学论文。例如,在我的书《 Mocks, Fakes and Stubs 》(尚未完成)中就有一篇写了认定测试,其中包括一些免费示例可供下载。一名学者做的项目研究也被我收录了进来,而且研究成果也发表在了《 the industrial applicability of TextTest 》论文中。在我的博客上有一篇关于认定测试的文章,里面讲述了其他人如何使用此类方法进行测试。Llewellyn Falco 特别为此主题整理了许多资料,包括截屏和视频,请点击在.Net 中使用认定测试查看。你还可以在 texttest 网站上找到一些文章和用户文档。
查看英文原文: Approval Testing with TextTest
评论