13

我通常会尽量避免重复并遵守 DRY 原则。但是,我想知道这样的案例:

public class Feature {
    final static String FEATURE_LABEL = "blah";

    public void doSomething() { ... }
    ...
}

public class FeatureTest {
    ...
    @Test
    public void doSomethingShouldMakeSomethingHappen() {
         assertEquals(Feature.FEATURE_LABEL, 
             feature.getSomethingHappens().getLabel());
    }

如果要求标签为“blah”并且有人将 FEATURE_LABEL 更改为“bleh”,则即使不再满足要求,测试也会通过。这是违反 DRY 的有效场所吗?

4

5 回答 5

16

是的,在这里使用文字。

从一个关于文字的问题中引用我自己的话:

硬编码文字应该出现在测试值的单元测试中,除非在单个测试类中重复使用太多值以至于局部常量很有用。

单元测试是对预期值的描述,没有任何抽象或重定向。想象一下你自己正在阅读测试——你想要将信息直接呈现在你面前。

于 2009-01-14T13:36:07.427 回答
5

要测试一些东西——任何东西——一个重要的考虑因素是你的测试条件独立于你正在测试的东西。否则,您的测试就没有单一、可靠的意义。每次检查对象发生变化时,它们都会变成其他测试。

不是很好的事情。

同样的想法也适用于单元测试。在上面的上下文中,您正在测试的字符串应该绝对独立于测试类中的内容。换句话说,是的,你可以而且应该在这里违反 DRY 原则。

于 2009-01-14T13:36:23.777 回答
2

表达其他人已经说过的话的另一种方式:如果测试永远不会失败,那么保留它是没有意义的。所以这没有意义:

assertEquals(Feature.FEATURE_LABEL, Feature.FEATURE_LABEL);

比如说,你有一个列表的限制。测试limit == limit是没有意义的,测试应该尝试将超过limit的元素放入列表中。

OTOH,如果您想确保在正确的位置使用常量(即它应该用作某些 UI 元素的标签),使用字符串常量(而不是新的文字)使用测试是有意义的)。

也就是说,对于我自己的 UI 测试,我使用抓取工具收集所有可见的字符串,并将生成的(长)字符串与文件的内容进行比较。这是一个非常简单的针对 UI 中的意外更改的全面测试,并且最适用于 HTML 中的 UI(我下载了 HTML 并进行了比较),但相同的模式可以应用于任何 UI。

于 2009-01-14T13:49:09.647 回答
1

我暂时坚持参考。

问题是,如果需求发生变化,应该会触发某人更改测试。可以说,更改测试的正确方法是将其更改为文字的新值,看到它失败,更改生产静态,看到它通过,然后更改测试以再次使用生产静态并看到它仍然通过。

这有任何意义吗?

于 2009-01-14T13:35:19.410 回答
0

我认为你所拥有的东西很好,是的,它是 DRY 的有效使用:如果这个值最终会出现在几个测试中,你不想在值发生变化时改变几个。但是您还应该添加一个额外的测试,即验证 Feature.FEATURE_LABEL 值的测试。

这是应用“一次且仅两次”的好地方:如果您只有一个测试 FEATURE_LABEL 的值的测试,那么我只使用文字字符串。只有当您使用它进行多个测试时,我才会开始使用引用(并为该值添加测试)。

于 2009-01-14T14:42:48.837 回答