代码之家  ›  专栏  ›  技术社区  ›  Paul Croarkin

生产代码常数和测试代码常数之间的干燥

  •  10
  • Paul Croarkin  · 技术社区  · 17 年前

    我通常会尽量避免重复,并坚持干燥原则。然而,我想知道这样一个案例:

    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());
        }
    

    如果要求标签为“bleh”,并且有人将特征标签更改为“bleh”,则即使不再满足要求,测试仍将通过。这是一个合法的地方吗?

    5 回复  |  直到 17 年前
        1
  •  14
  •   Community Mohan Dere    9 年前

    是的,在这里使用文字。

    引用我自己的话 a question on literals :

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

    单元测试是对期望值的描述,没有任何抽象或重定向。想象一下你正在阅读测试——你希望信息真实地呈现在你面前。

        2
  •  5
  •   G S    17 年前

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

    这不是一件好事。

    同样的想法也适用于单元测试。在上面这样的上下文中,测试所针对的字符串应该完全独立于测试类中的内容。换句话说,是的,你可以而且 应该 这违反了干燥原则。

        3
  •  2
  •   Aaron Digulla    17 年前

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

    assertEquals(Feature.FEATURE_LABEL, Feature.FEATURE_LABEL);
    

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

        4
  •  1
  •   Jon Skeet    17 年前

    我暂时还是坚持这个说法。

    触发某人更改测试。可以说,更改测试的正确方法是将其更改为文本形式的新值,看到它失败,更改生产静态,看到它通过,然后更改测试以再次使用生产静态,看到它仍然通过。

    这有什么意义吗?

        5
  •  0
  •   Jeffrey Fredrick    17 年前

    我认为你所拥有的是好的,是的,它是DRY的一个有效用法:如果这个值将在几个测试中结束,那么如果这个值改变,你不想改变几个。但是您还应该添加一个额外的测试,即验证Feature.Feature\u标签值的测试。

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