有关单元测试库/框架的最佳实践是什么?

时间:2009-09-08 15:24:46

标签: unit-testing frameworks

上下文

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

问题

基本上,我正在努力遵守some posts here中有关单元测试的原则和最佳实践,但它们在专门对单元测试库或框架方面似乎存在冲突。 / p>

例如,基本测试涉及“创建工件”。还有一个“删除神器”。但是,由于单元测试应该是独立的并且在完成之后恢复世界状态,所以这些测试看起来都有点相关:在测试工件创建时,我们需要在测试结束时通过实际来清理状态删除它。这意味着工件移除本身是隐式测试的。同样的推理适用于测试工件移除:为了设置世界以便可以测试工件移除,我们需要首先创建一个新工件。

当我们需要对相关子工件的创建和删除进行单元测试时,情况变得更加复杂,我们需要相应地设置世界。

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

[create artifact] - > [create sub artifact] - > [remove sub artifact] - > [remove artifact]

有了这个原则,整个库/框架都经过了单元测试,并且在整个测试套件运行结束时恢复了世界状态。但是,这意味着测试套件中间的任何故障都会“打破世界”。

哪些最佳做法和指南可能有助于协调这些相互冲突的需求?

参考

What makes a good unit test?

Is it bad form to have unit test calling other unit tests?

6 个答案:

答案 0 :(得分:2)

通过“恢复世界状态”,你的意思是清理一个数据库,或类似的东西?

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

因此,您可以使用其他测试,这听起来更像是“黑盒子”测试,或集成测试,或者您想要调用的任何测试。他们依赖外部状态,必须建立,监控,拆除等。

你绝对应该期望它们比单元测试更脆弱。

我个人认为,一旦你接受了这些测试......这实际上取决于你。你的建议听起来并不合理。

我倾向于构建一套强大的独立单元测试,并依赖于您所描述的最终“胶水测试”测试。因此,它们不是太详细,也不会尝试锻炼图书馆的各个方面。

答案 1 :(得分:1)

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

为每个测试设置灯具,然后将其拆除(恢复状态)。大多数情况下,如果将变量保持为测试方法的局部变量,则不需要拆卸方法(实现取决于测试框架)。

如果您的图书馆跟踪状态,您可能还有其他问题(例如线程安全)。

答案 2 :(得分:1)

根据Glen Beck和co使用的单元测试的严格定义,在您的情况下创建单元测试很可能实际上是一个坏主意

对于工作站呼叫范围之外的任何人使用库,你肯定和无可争议地需要的是一整套用户级API系统测试。以与客户端代码相同的方式运行整个系统的那些,而不是孤立的一块一块。

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

  • 执行时间(受您所用语言和性质的影响)。
  • 内部隐藏的复杂性
  • API的大小
  • 图书馆的同步开发人员数量
  • 构建时间
很可能你可以设置一套完整的系统测试,涵盖需要覆盖并在几秒钟内执行的所有内容。您可以通过对最低级别和最复杂的10%代码进行一系列重点单元测试来补充这一点,但在单元级别完全覆盖所有内容可能会浪费精力。

注意:对于作为库的系统,像Junit这样的单元测试工具非常适合创建这样的完整系统测试。因此很多人最终称他们为单元测试。这是好的,只要你不参与给予他们名称改变他们应该工作的方式的论点。

进行良好单元测试的品质不仅不适用,而且可能是有害的。

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

  • 使测试独立,因此可以单独运行,也可以按任意顺序运行。
  • 以已知的清洁状态开始每个测试。
  • 使用灯具构建环境。再看看db:unit。我希望数据库具有良好的“规范”状态,并在每次测试(或回滚)之前恢复它。

我不同意你的一个假设:测试必须在完成之前恢复其状态。你也可以说测试运​​行者有责任这样做;像db:unit这样的工具就是这样做的。它们允许您更自由地编写测试。

您的顺序测试是有道理的,但在实践中变得困难。 (我已经尝试过)如你所说,你没有得到关于失败的好报告。此外,随着程序超过4次测试,您需要确定序列中的哪个位置插入测试,以便数据适合它。它很快就会变得难以理解。 (想想100或1000的测试)。这就是测试夹具(或工厂)有意义的原因。

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

答案 5 :(得分:0)

阅读“XUnit测试模式”一书,但阅读Gerard Meszaros(http://xunitpatterns.com/)。它很好地涵盖了这一主题。

相关问题