A Few Thoughts on Unit Test Scaffolding

The following text is a partial translation of the original English article, performed by ChatGPT (gpt-3.5-turbo) and this Jekyll plugin:

当我在单元测试方法中重复自己,创建相同的对象和准备数据来运行测试时,我对自己的设计感到失望。长测试方法中存在大量代码重复看起来不对劲。为了简化和缩短它们,至少在Java中有两个选项:1)通过@Before@BeforeClass初始化的私有属性,和2)私有静态方法。它们都对我来说看起来不符合面向对象编程的原则,我认为还有另一种选择。让我解释一下。

JUnit官方建议使用测试夹具

我认为这个测试在做什么是显而易见的。首先,在prepare()中,它创建了一个Folder类型的”test fixture”。这个”test fixture”在所有三个测试中都被用作Metrics构造函数的参数。在这里被测试的是Metrics这个真正的类,而this.folder是我们需要用来测试它的东西。

这个测试有什么问题?有一个严重的问题:测试方法之间的耦合。测试方法(以及所有的测试)必须完全与其他测试隔离开来。这意味着更改一个测试不能影响其他测试。在这个例子中,情况并非如此。当我想要更改countsWords()测试时,我必须更改before()的内部,这将影响测试”类”中的其他方法。

虽然对JUnit表示敬意,但在@Before@After中创建测试fixture的想法是错误的,主要是因为它鼓励开发人员将测试方法耦合在一起。

下面是我们如何改进测试并隔离测试方法的方法:

现在看起来好点了吗?我们还没到那一步,但现在我们的测试方法已经完全隔离了。如果我想要更改其中一个方法,不会影响其他方法,因为我将所有配置参数传递给了一个私有静态实用方法folder()

一个实用方法,嗯,闻起来有点问题。

这个设计的主要问题是,虽然它比之前的设计要好得多,但它无法防止测试”类”之间的代码重复。如果我需要在另一个测试用例中使用一个相似的类型为Folder的测试装置,我将不得不将这个静态方法移到那里。甚至更糟糕的是,我将不得不创建一个实用类。是的,在面向对象编程中,没有比实用类更糟糕的东西了。

一个更好的设计是使用”假”对象而不是私有静态实用程序。下面是如何实现的。首先,我们创建一个假类并将其放入src/main/java。这个类可以在测试中使用,如果需要的话也可以在生产代码中使用(Fk表示”fake”):

这是我们测试的现状:

你觉得呢?这不是比JUnit提供的更好吗?这不是比实用方法更具可重用性和可扩展性吗?

总之,我认为单元测试中的脚手架必须通过与生产代码一起交付的虚拟对象来完成。

Translated by ChatGPT gpt-3.5-turbo/42 on 2023-11-28 at 14:40

sixnines availability badge   GitHub stars