我通常会尽量避免重复并遵守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的有效地点?
答案 0 :(得分:13)
是的,请在这里使用文字。
从a question on literals引用自己:
硬编码文字应该出现在测试值的单元测试中,除非在单个测试类中重复使用一个局部常量有用的值。
单元测试是对期望值的描述,没有任何抽象或重定向。想象一下你自己在阅读测试 - 你希望信息完全在你面前。
答案 1 :(得分:5)
测试某些东西 - 任何东西 - 一个重要的考虑因素是你的测试条件与你正在测试的东西无关。否则,您的测试没有单一,可靠的含义;每当被检查对象发生变化时,它们就会变成其他测试。
不是一件好事。
同样的想法适用于单元测试。在上面的上下文中,您正在测试的字符串应该完全独立于测试类中的内容。换句话说,是的,你可以 在这里违反DRY原则。
答案 2 :(得分:2)
表达其他人已经说过的不同方式:如果测试永远不会失败,那么保持它是没有意义的。所以这没有意义:
assertEquals(Feature.FEATURE_LABEL, Feature.FEATURE_LABEL);
例如,假设您对列表有限制。测试limit == limit是没有意义的,测试应该尝试将多个限制元素放入列表中。
OTOH,如果你想确保在正确的位置使用常量(即它应该用作某些UI元素的标签),使用字符串常量(而不是一个新的文字。)
也就是说,对于我自己的UI测试,我使用刮刀收集所有可见的字符串,并将结果(长)字符串与文件内容进行比较。这是一个非常简单的全能测试,用于UI中的意外更改,最适合HTML中的UI(我下载HTML并进行比较),但相同的模式可以应用于任何UI。
答案 3 :(得分:1)
我暂时坚持参考。
问题是,如果需求发生变化,应触发某人更改测试。可以说,更改测试的正确方法是将其更改为新值作为文字,看到它失败,更改生产静态,看到它通过,然后更改测试以再次使用生产静态并看到它仍然通过。
这有意义吗?
答案 4 :(得分:0)
我认为你所拥有的是好的,是的,它是对DRY的有效使用:如果这个值最终会在多个测试中结束,那么如果值发生变化则不想更改几个。但是你还应该添加一个额外的测试,验证Feature.FEATURE_LABEL的值。
这是一个应用“一次且仅两次”的好地方:如果你只有一个测试,其中测试了FEATURE_LABEL的值,那么我只使用文字字符串。只有当你开始使用引用时,才会使用它进行多次测试(并为值添加测试)。