什么是一个单元测试,真的吗?这里真的有这么大的二分法吗?
我们在这样一个领域中工作:从缓冲区末尾读取一点点的字面量可能会使程序完全崩溃,或导致程序产生完全不正确的结果,或者如最近的“ HeartBleed” TLS错误所证明的那样,在整个系统范围内放置了一个安全的虚拟机。打开时不会产生任何直接的缺陷证据。
从这些系统中消除所有复杂性是不可能的。但是我们的工作是尽可能地减少和管理这种复杂性。
单元测试是否是一种测试,例如,它可以确认在三个不同的系统中成功发布了预订,创建了日志条目并发出了电子邮件确认?
我要说不。那是一个集成测试。那些绝对肯定有他们的位置,但是它们也是一个不同的主题。
集成测试旨在确认整个“功能”的总体功能。但是,该功能背后的代码应分解为简单的,可测试的构建块,也称为“单元”。
因此,单元测试的范围应非常有限。
这意味着由单元测试测试的代码应具有非常有限的范围。
这进一步意味着,良好设计的支柱之一是将您的复杂问题分解为较小的,单一用途的部件(在可能的范围内),这些部件可以相对隔离地进行测试。
最终得到的是一个由可靠的基础组件组成的系统,并且您知道这些基础代码中的任何一个是否因为您编写了简单,小型,有限范围的测试来告知您而导致破坏。
在许多情况下,您可能还应该每个单元进行多个测试。测试本身应该是简单的,尽可能地测试一种和一种行为。
我认为,测试非平凡,复杂,复杂的逻辑的“单元测试”的概念有点矛盾。
因此,如果发生了这种故意的设计故障,那么除非被测代码单元的基本功能发生了变化,否则单元测试在世界上怎么会突然开始产生误报?如果发生了这种情况,那么您最好相信其中存在一些非显而易见的涟漪效应。您的破损测试(似乎正在产生误报)实际上是在警告您,某些更改破坏了代码库中更广泛的依赖关系,需要对其进行检查和修复。
其中一些单元(其中许多单元)可能需要使用模拟对象进行测试,但这并不意味着您必须编写更复杂或更复杂的测试。
回到我的人为保留系统的示例,您确实无法在每次单元测试代码时都将请求发送到实时保留数据库或第三方服务(甚至是其“开发”实例)。
因此,您可以使用提供相同接口协定的模拟程序。然后,测试可以验证相对较小的确定性代码块的行为。木板下面的所有绿色都告诉您构成基础的块没有损坏。
但是各个单元测试本身的逻辑仍然尽可能简单。