单元测试的编写和维护成本更低,但它们并不涵盖所有场景。它们之间的正确平衡是什么?
8 回答
区分这两种测试的意图和范围很重要:
单元测试通常在模块/类级别测试特定功能,例如 create-X、update-Y、foo-the-bar、compact-the-whizbang 等。一个类可能有多个单元测试
功能测试,也称为“验收测试”,通常测试从最外层界面到处理结束的用例场景,例如从用户界面到数据库再返回,从输入过程到通知实用程序, ETC。
这两种类型的测试不能互换,并且通常是不相交的。因此,在它们之间取得“平衡”的想法毫无意义。您要么需要它们,要么不需要它们。
如果您指的是在测试框架中对每种类型的测试进行编码的难易程度,那是一个不同的问题——但是框架的使用(例如,NUnit 与用户机器人)不会改变测试框架的类型/性质测试。
一般来说,最好的“平衡”是对信心和完整性进行单元测试,对客户接受进行功能测试
我同意 Steven Lowe 的观点,即单元测试和功能测试之间没有权衡,因为它们用于非常不同的目的。
单元测试是关于方法和类型验证,以及回归测试。功能测试是关于功能、场景和可行性测试。在我看来,几乎没有重叠,
如果有帮助,这是我的测试类别。
开发人员由内而外,专注于代码:
- 断言 - 验证数据流和结构
- 调试器 - 验证代码流和数据
- 单元测试 - 验证每个功能
- 集成测试 - 验证子系统
- 系统测试 - 验证功能
- 回归测试 - 验证缺陷保持不变
- 安全测试 - 验证系统不容易被渗透。
测试人员从外部开始,向内工作,专注于功能:
- 验收测试 - 验证最终用户要求
- 场景测试 - 验证真实世界的情况
- 全局测试 - 验证可行的输入
- 回归测试 - 验证缺陷保持不变
- 可用性测试 - 验证系统是否易于使用
- 安全测试 - 验证系统不容易被渗透
- 代码覆盖率 - 测试未触及的代码
- 兼容性 - 与以前的版本
- 寻找怪癖和粗糙的边缘。
最终用户从外部工作,通常很少关注:
- 验收测试 - 验证最终用户要求
- 场景测试 - 验证真实世界的情况
- 可用性测试 - 验证系统是否易于使用
- 寻找怪癖和粗糙的边缘。
我喜欢Brian Marick关于自动化测试的象限,其中区别是面向业务与技术,支持编程与批评产品。
有了这个框架,平衡的问题就变成了,我现在需要什么?
在我目前正在开发的应用程序上,功能测试可能有 10:1 的单元。单元测试的工作很简单,比如从数据库中检索实体、数据库/网络连接的错误处理测试等。这些东西运行得很快——几分钟或更短,并且由开发人员每天运行。
功能测试虽然较少,但往往是厨房水槽方法 - 用户能否完成订单等往往涵盖业务领域,最终由业务分析和运营运行 - 对我们来说很遗憾,通常是手动运行。这些事情需要几周的时间来运行,并且通常需要完成一个发布周期。
我目前的项目有大约 60% 的单元测试覆盖率,所有用户故事在 selenium 测试中都有用户故事的快乐日覆盖率,有些还有额外的覆盖率。
我们一直在讨论这个问题:为了更高的覆盖率,推动单元测试覆盖越来越荒谬的场景真的有什么意义吗?
争论是扩展 selenium 测试增加了对具有商业价值的事物的测试覆盖率。客户真的关心可能失败的单元测试极端案例吗?
当您擅长 selenium 测试时,编写具有商业价值的新测试的成本就会降低。对我们来说,它们就像单元测试一样简单。
运行时成本是另一个问题。我们有一小群盒子一直在运行这些测试。
所以我们倾向于更喜欢网络测试,可能是因为我们已经擅长编写它们并且它们提供了不可否认的商业价值。
最初,由于验收测试的初始成本因素,我倾向于选择单元测试而不是功能/验收测试。然而,随着时间的推移,我改变了我的理念,现在我强烈支持尽可能选择验收测试,并且只在验收测试不能满足我的需求时使用单元测试。
选择验收而不是单元测试的基本原理与SOLID的基本原理相同代码。您的实现应该能够通过重构等发生巨大变化,但所有业务案例 - 验收测试 - 应该能够保持不变并证明可接受的系统行为(测试通过)。对于单元测试,测试与实现代码之间通常存在自然的强耦合。即使它是测试代码,它仍然是代码,应该避免强耦合。通过选择验收测试,您通常会沿着成功的螺旋式下降,以创建精心计划的、可消耗的解耦 api,让您的实现在幕后更改,而无需强制更改测试。此外,您的开发人员实施思想与业务系统行为思想一致。最后,我发现所有这些对业务和编码人员的满意度都更好。
从理论的角度来看,我经常问自己,如果不能通过验收测试来测试一段代码,为什么那段代码应该存在?IE - 如果它不是有效业务场景的一部分,那么该代码是否增加了价值,或者目前是否会增加成本?
此外,如果您很好地评论/记录您的验收测试,那么这些评论/文档通常是系统中最新和最准确的语言 - 这通常可以让您避免使用其他价值较低的文档方法。单元测试不适合这种形式的“业务术语”通信。
最后,我并没有仅仅从我的个人发展形成这个观点,在我的“非常公司”的工作环境中,几个不同的项目团队已经证明它是成功的。
测试应该快速运行并帮助定位问题。单元测试允许您通过仅测试有问题的模块来做到这一点。然而,功能/集成/验收测试可以在大多数 Web 场景中足够快地运行。
我曾经读到单元测试是一个“可执行要求”,这对我来说非常有意义。如果您的测试不专注于证明业务需求,那么它真的没有用。如果您有详细的要求(那就是酸测试),那么您将编写许多单元测试来练习每个可能的场景,从而确保您的数据结构算法和逻辑的完整性。如果您正在测试一些不是要求的东西,但您知道必须为真才能通过测试,那么您很可能缺少要求。