【发布时间】:2019-10-31 10:56:48
【问题描述】:
在单元测试的上下文中,什么是“单元”?
【问题讨论】:
标签: unit-testing language-agnostic
在单元测试的上下文中,什么是“单元”?
【问题讨论】:
标签: unit-testing language-agnostic
我通常将其定义为通过单一方法的单一代码执行路径。这来自经验法则,即测试方法所需的单元测试数量等于或大于方法的 cyclomatic complexity 数量。
【讨论】:
虽然定义可能会有所不同,但“单元”是一段独立的代码。
通常,它是一个单独的类。
但是,很少有类是孤立存在的。因此,您经常需要模拟与您的测试类协作的类。
因此,“单元”(也称为“夹具”)是一个可测试的东西——通常是一个类加上协作者的模型。
您可以使用单元测试技术轻松测试相关类的包。我们一直这样做。这些装置中很少或没有模拟。
事实上,您可以将整个独立应用程序作为单个“单元”进行测试。我们也这样做。提供一组固定的输入和输出,以确保整个应用程序正确执行。
【讨论】:
单元是可以单独测试的任何元素。因此,几乎总是在 OO 环境中测试方法,以及该类的方法之间存在紧密耦合的某些类行为。
【讨论】:
根据我的经验,关于“什么是单元”的争论是浪费时间。
更重要的是“测试有多快?”快速测试以 100+/秒的速度运行。慢速测试运行速度很慢,以至于您不会在每次停下来思考时都反射性地运行它们。
如果您的测试很慢,您将不会频繁地运行它们,从而使错误注入和错误检测之间的时间变长。
如果您的测试速度很慢,您可能无法获得单元测试的设计优势。
想要快速测试?关注 Michael Feather 的rules of unit testing。
但是,如果您的测试速度很快,并且它们正在帮助您编写代码,那么谁在乎它们的标签是什么?
【讨论】:
我们将“单元”定义为单个类。
正如您正确断言的那样,“单元”是一个模棱两可的术语,当开发人员仅使用该表达式而不添加细节时,这会导致混淆。在我工作的地方,当我们说“单元测试”、“验收测试”等时,我们会花时间定义我们的意思。当有人新加入团队时,他们会了解我们的定义。
从实际的角度来看,对于“单位”是什么,可能总会存在意见分歧。我发现重要的是在项目的上下文中一致地使用该术语。
【讨论】:
如果我工作,一个“单元”就是一个函数。那是因为我们不允许在我们的设计中使用除功能分解之外的任何东西(没有 OOP)。我 100% 同意威尔的回答。至少这是我在引擎和飞行控制以及各种其他系统的嵌入式编程工作范式中的答案。
【讨论】:
可以是不同的东西。一个类、一个模块、一个文件……选择您想要的测试粒度。
【讨论】:
我会说一个单元是一个可以在应用程序中使用的“黑匣子”。它具有已知接口并提供明确定义的结果。这是必须根据设计规范工作并且必须是可测试的。
话虽如此,当我在这样的“黑匣子”中构建项目时,我经常使用单元测试作为开发辅助。
【讨论】:
我的理解(或理由)是,单元应该遵循类似于代码的层次分解的抽象层次和范围。
方法是低抽象级别的小型且通常是原子(概念上)操作,因此应该对其进行测试
类是提供服务和状态的中级概念,因此应该进行测试。
整个模块(特别是如果它的组件被隐藏)是一个具有有限接口的高级概念,因此应该对其进行测试等。
由于许多错误是由多个方法和类之间的交互产生的,我看不到仅对单个方法进行单元测试可以实现覆盖率,直到您已经有了利用每个重要组合的方法,但这表明您没有在编写客户端代码之前没有进行足够的测试。
【讨论】:
那不重要。当然,您要求开始进行单元测试是正常的,但我再说一遍,这并不重要。
单位类似于:
但是,“单元”、函数或方法也可以从应用程序中调用另一个“单元”,同样由测试执行。所以“单元”可以跨越几个函数甚至几个类。
“测试比单元更重要”(testivus)。一个好的测试应该是:
【讨论】:
我会说单元测试中的一个单元是一个类的单一职责。
这个观点当然来自我们的工作方式:
在我的团队中,我们使用术语单元测试来测试单个类的职责。我们使用模拟对象来覆盖所有其他对象,以便真正隔离类的职责,并且在其他对象中出现错误时不会受到影响。
我们使用术语集成测试来测试两个或多个类如何一起运行,以便我们看到实际功能在那里。
最后,我们帮助我们的客户编写验收测试,这些测试作为一个整体对应用程序进行操作,以了解当“用户”使用应用程序时实际发生了什么。
这让我觉得这是一个很好的描述。
【讨论】: