The following text is a partial translation of the original English article, performed by ChatGPT (gpt-3.5-turbo) and this Jekyll plugin:
常量…我之前写过一些关于它们的东西,主要是说它们是一件坏事,如果公开的话。它们减少了重复,但引入了耦合。消除重复的更好方法是通过创建新的类或方法——传统的面向对象编程方法。这似乎是有道理的,在我们的项目中,我看到越来越少的公共常量。在一些项目中,我们根本没有它们。但有一件事仍然困扰着我:单元测试。大多数程序员似乎认为,当静态分析指出同一文件中有太多相似的字面值时,摆脱它们的最好方法是使用私有静态字面值。这是错误的。
单元测试自然会产生大量重复的代码。测试方法包含类似或几乎相同的功能,这几乎是不可避免的。嗯,我们可以使用更多的@Before
和@BeforeClass
功能,但有时是不可能的。我们可能在一个FooTest.java
文件中有20个测试方法。在一个”before”中准备所有对象是不可能的。因此,我们必须在我们的测试方法中一次又一次地做某些事情。
让我们来看看我们的Takes Framework中的一个类:VerboseListTest
。这是一个单元测试,它有一个问题,我正在试图告诉你。看看那个MSG
私有字面值。它首次在setUp()
方法中作为对象构造函数的参数使用,然后在几个测试方法中用于检查该对象的行为。让我简化一下那段代码:
这基本上就是VerboseListTest
中所发生的事情,这是非常错误的。为什么?因为这个共享的文字常量MSG
在这两个测试方法之间引入了一种不自然的耦合。它们没有任何共同之处,因为它们测试的是Foo
类的不同行为。但是这个私有常量将它们联系在一起。现在它们某种程度上是相关的。
当我想要修改其中一个测试方法时,我可能需要同时修改另一个方法。比如说,我想要查看doSomethingElse()
在封装的消息为空字符串时的行为。我该怎么办?我改变FooTest.MSG
常量的值,而这个常量又被另一个测试方法使用。这就是所谓的耦合。而且这是一件坏事。
我们该怎么办?嗯,我们可以在两个测试方法中都使用那个"something"
字符串字面量:
如你所见,我摆脱了setUp()
方法和私有静态文字常量MSG
。现在我们有了什么?代码重复。字符串"something"
在测试类中出现了四次。没有任何静态分析器会容忍这种情况。而且,在VerboseListTest
中有七个(!)测试方法在使用MSG
。因此,我们将会有14个"something"
的出现,对吗?是的,没错,这很可能是这个测试用例的作者之一引入常量的原因——为了消除重复。顺便说一下,@Happy-Neko在请求合并#513中做了这个修改,@carlosmiranda
审核了代码,而我则批准了这些更改。所以,三个人都犯了/批准了这个错误,包括我自己。
那么,如何避免代码重复,同时又不引入耦合呢?答案是:
这些字面值必须是不同的。当静态分析器在很多地方看到“something”时,它就是这样说的。它质疑我们——为什么它们是相同的?在每个地方都使用“something”真的很重要吗?为什么不能使用不同的字面值?当然我们可以。而且我们应该。
归根结底,每个测试方法必须有自己的一组数据和对象。它们绝不能在测试方法之间共享。测试方法必须始终是独立的,没有任何共同之处。
考虑到这一点,我们可以很容易地得出结论,像setUp()这样的方法或测试类中的任何共享变量都是“邪恶”的。它们不能被使用,也不能存在。我认为它们在JUnit中的发明给Java代码带来了很多伤害。
Translated by ChatGPT gpt-3.5-turbo/42 on 2023-12-15 at 06:26