Unit testing 关于库/框架的单元测试的最佳实践是什么? 上下文

Unit testing 关于库/框架的单元测试的最佳实践是什么? 上下文,unit-testing,frameworks,Unit Testing,Frameworks,我正在努力为我正在设计的库/框架编写一组单元测试。对于上下文,请将我的库视为相关对象层次集上的对象层 问题: 基本上,我试图坚持中所述的单元测试原则和最佳实践,但它们似乎与库或框架的具体单元测试相冲突 例如,一个基本测试涉及到“创建工件”。还有一个是“移除工件”。但是,由于单元测试应该是独立的,并在完成后恢复世界的状态,因此这两个测试似乎都有些关联:在测试工件创建时,我们需要在测试结束时通过实际删除它来清理状态。这意味着工件移除本身是隐式测试的。同样的道理也适用于测试工件移除:为了建立一个可以测

我正在努力为我正在设计的库/框架编写一组单元测试。对于上下文,请将我的库视为相关对象层次集上的对象层

问题: 基本上,我试图坚持中所述的单元测试原则和最佳实践,但它们似乎与库或框架的具体单元测试相冲突

例如,一个基本测试涉及到“创建工件”。还有一个是“移除工件”。但是,由于单元测试应该是独立的,并在完成后恢复世界的状态,因此这两个测试似乎都有些关联:在测试工件创建时,我们需要在测试结束时通过实际删除它来清理状态。这意味着工件移除本身是隐式测试的。同样的道理也适用于测试工件移除:为了建立一个可以测试工件移除的世界,我们需要首先创建一个新的工件

当我们需要对相关子工件的创建和移除进行单元测试时,情况就复杂了,为此我们需要相应地设置世界

我倾向于按顺序执行一组相关的单元测试,这样每个单元测试都是离散的(即,只测试一件事,只测试一件事),但依赖于顺序中以前的测试来逐步设置世界。然后,我的序列可以如下所示:

[创建工件]->[创建子工件]->[删除子工件]->[删除工件]

根据这一原则,整个库/框架都进行了单元测试,并且在测试套件的整个运行结束时恢复了世界的状态。然而,这意味着测试套件中间的任何故障都会“破坏世界”。 哪些最佳实践和指导方针可能有助于协调这些相互冲突的需求

工具书类


不知道你在用什么语言编程。在Java中,您可以使用JUnitAPI创建TestSuite。将单个子测试添加到测试套件中,并作为一个整体运行测试套件。

所谓“恢复世界状态”,您的意思是清理数据库,或者类似的东西

在这种情况下,您可能已经有了一些模拟持久层的单元测试。这将允许您单独运行单元测试,而不依赖于在测试之间保留状态

这就剩下了其他测试,它们听起来更像是“黑盒”测试,或者集成测试,或者任何你想称之为它们的测试。它们依赖于必须建立、监控、拆除等的外部状态

您肯定应该期望它们比单元测试更脆弱

我个人的看法是,一旦你参加了这些测试。。。这要看情况而定。你的建议听起来并不不合理


我倾向于构建一套强大的独立单元测试,并依赖于您描述的用于最终“粘合测试”的测试。因此,它们不太详细,也不要尝试使用库的每个方面。

好的单元测试是独立的。测试的运行顺序(或者即使运行其他测试)应该无关紧要

为每个测试设置夹具,然后将其拆下(恢复状态)。如果您将变量保留在测试方法的本地,那么大多数情况下您不需要拆卸方法(实现取决于测试框架)


如果您的库跟踪状态,您可能会遇到其他问题(如线程安全)。

以下是一些有帮助的最佳做法:

  • 使测试独立,这样它们就可以单独运行,并且可以按任何顺序运行
  • 在已知的干净状态下开始每个测试
  • 使用固定装置构建环境。再看看db:unit。我希望数据库有一个良好的“规范”状态,并在每次测试(或回滚)之前恢复它
我不同意您的一个假设:测试必须在完成之前恢复其状态。你也可以说这是测试运行者的责任;像db:unit这样的工具可以做到这一点。它们允许您更自由地编写测试

您的顺序测试是有意义的,但在实践中会变得困难。(我试过)正如你提到的,你没有收到好的失败报告。此外,当程序超过4个测试时,您需要确定在序列中插入测试的位置,以便数据正好适合它。这将很快变得难以推理。(想想100或1000次测试)。这就是为什么测试修复程序(或工厂)是有意义的


Kent Beck的测试驱动开发:通过示例详细讨论了这个主题。

按照Glen Beck及其同事对单元测试的严格定义,在您的情况下创建单元测试可能是个坏主意

要让工作站范围之外的任何人使用库,您无疑需要一整套用户级API系统测试。以客户机代码相同的方式运行整个系统,而不是孤立地一块一块地运行

一旦你有了这些,那么取决于:

  • 执行时间(受您的语言和所做工作的性质影响)
  • 内部隐藏复杂性
  • API的大小
  • 库上同步开发人员的数量
  • 构建时间
很可能您可以设置一套完整的系统测试,覆盖所有需要覆盖的内容,并在几秒钟内执行。您可以在最低级别和最复杂的10%代码上进行一小部分集中的单元测试来补充这一点,但是在单元级别上全面覆盖所有内容很可能是白费力气

注意:对于作为库的系统,像Junit这样的单元测试工具非常适合creati