何时在单元测试中使用测试脚本?
我目前正在从事一个已经生产了两年以上的项目。该项目广泛使用了单元测试和脚本化UI测试。最初的单元测试涵盖了系统框架,业务规则和状态转换(或者工作流)。测试脚本用于黑盒测试。但是,随着时间的流逝,维护我们全套的单元测试的成本变得越来越昂贵,尤其是与状态相关的测试。
经过一些调查,我们发现测试脚本比与工作流程相关的单元测试更有效(即,提供更好的覆盖范围)并且维护成本更低。这并不是说单元测试的价值已被完全否定,但这确实提出了一个问题,即是否可以放弃某些类的单元测试以支持测试脚本。
我们的项目在迭代增量模型上运行。
解决方案
关于"单元测试的局限性"问题的SO答案之一是,当单元测试用于测试与INTEGRATION而不是功能相关的任何东西时,它们就会变得混乱。连接和使用外部服务(数据库,到另一台服务器的SSH等)和用户界面是其中两个示例。
这并不是说我们不能对这些事情使用单元测试,仅仅是因为涵盖所有基础的困难使得使用这种测试方法不值得,除非在可靠性方面至关重要。
我对所有自定义JavaScript UI代码(模板引擎,效果和动画等)使用"脚本测试",如果操作正确,我会发现它快速,可靠。
两件事
- 单元测试-开发人员-验证代码是否正确
- 验收测试-客户/ QA / BA-验证开发了正确的代码。
这两个类别应该是截然不同的,并且都起着同等重要的作用。我们提到的测试脚本属于第二类。为此,我建议使用FIT / Fitnesse之类的东西。如果那不可行,请使用测试脚本/记录重放样式工具。但是,不要丢掉好的单元测试。."维护测试的成本已经变得昂贵"是什么意思?
通常,我们可以使用单元测试来完全做到这一点:测试单元。更确切地说,测试一个单元是否符合其接口规范/合同。如果单元测试失败,我们将确切知道问题出在哪里:问题在被测试的单元中。这使调试更加容易,尤其是因为可以自动处理单元测试的结果。这里会想到自动回归测试。
如果要离开单元测试的范围,或者想测试无法通过单元测试很好地测试的事物,则可以开始使用脚本化UI测试。例如。当我们测试与许多无法模拟的外部API接口的代码时。现在,我们可以引发某些错误,但是要更深入地查找故障在代码中的确切位置是很难的。
实际上,测试有四个级别,其中三个可能涉及脚本,而第一个则不涉及。
- 单元测试:在完全隔离系统其余部分的情况下测试类或者方法
- 组装测试:测试系统中的方案是否与系统外部的其他组件完全隔离(即来自不同的功能域)
- 集成测试:测试系统,包括来自外部的输入和去往外部其他系统(即来自其他功能域)的输出。
- 验收测试:如Gishu所说的最终验证,用于检查正确的代码(即正确的功能)是否存在。
功能域示例:服务层总线,即所有能够在总线上公开其服务的项目(通常封装一些核心参考数据库)。
我们可以这样做:
- 发布者类的单元测试
- 与SLB的其他组件协作为发布者机制进行汇编测试
- 针对SLB服务和在SLB之外开发的其他组件以及服务客户端的集成测试
- 整个系统的验收测试。
如前所述,最后3种测试可能涉及繁重的脚本编写,并且可以快速覆盖更多代码。根据要进行单元测试的类/方法的绝对数量,良好的组装测试可能是更好的方法。
与单元测试相比,我经历了不止一种方式的痛苦,特别是在那些成员对单元测试完全不热衷并且其中许多人只是忽略或者注释掉测试的项目中。能够欺骗源代码控制,节省时间等。一位前同事甚至为此创造了"截止日期驱动的开发"一词。
我认为,面对此类挑战时,以下是一些针对单元测试的准则:
- 丢弃过时的测试-有时,如果测试本质上是不准确或者不相关的,则尝试更新数百至数千行测试毫无意义。立即丢弃测试。不要"忽略"它们,也不要将它们注释掉。完全删除它们。
- 为新功能编写测试-任何新功能仍需要进行单元测试和以可单元测试的方式编写。
- 编写错误修复测试-在对应用程序进行回归测试时,可能需要确保错误修复具有单元测试以确保已修复该错误。
- 涉及代码覆盖范围的问题–我敢肯定,这可能会引起一些争议,但是在确保功能和使用测试作为拖延工作的借口之间有一条很好的界限。重点应该放在确保核心功能上,而不要遵循任何任意代码覆盖率的百分比。
话虽这么说,我仍然认为单元测试不应完全丢弃。测试脚本和单元测试有其自己的目的。但是,在过度狂热地维护TDD和面对企业应用程序开发的现实之间应该取得平衡。