生产和测试代码常量之间的 DRY
我通常会尽量避免重复并坚持 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 的有效地点吗?
I normally try to avoid duplication and adhere to the DRY principle. However, I'm wondering about a case like this:
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());
}
If the requirement is that the the label be "blah" and someone changes FEATURE_LABEL to "bleh", the test will pass even though it no longer meets the requirement. Is this a valid place to violate DRY?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
是的,这里使用文字。
引用我自己的关于文字的问题:
硬编码文字应该出现在测试值的单元测试中,除非在单个测试类中重复使用了太多值,以至于局部常量很有用。
单元测试是对期望值的描述,没有任何抽象或重定向。 想象一下您自己正在阅读测试 - 您希望信息就在您面前。
Yes, use a literal here.
Quoting myself from a question on literals:
Hardcoded literals should appear in unit tests for the test values, unless there is so much reuse of a value within a single test class that a local constant is useful.
The unit tests are a description of expected values without any abstraction or redirection. Imagine yourself reading the test - you want the information literally in front of you.
要测试某些东西(任何东西),一个重要的考虑因素是您的测试条件独立于您正在测试的内容。 否则,你的测试就没有单一、可靠的意义; 每当被检查的对象发生变化时,它们就会变成其他测试。
不是什么好事。
同样的想法也适用于单元测试。 在上面这样的上下文中,您要测试的字符串应该完全独立于测试类中的内容。 换句话说,是的,您可以而且应该在这里违反 DRY 原则。
To test something -- anything -- an important consideration is that your test conditions stand independent of what you're testing. Otherwise, your tests don't have a single, dependable meaning; they morph into some other test every time the object under examination changes.
Not a very good thing.
The same idea applies to unit tests. In a context like above the string you're testing against should be absolutely independent of what's inside the tested class. In other words, yes, you can and should violate the DRY principle here.
另一种方式来表达其他人已经说过的话:如果测试永远不会失败,那么保留它就没有意义。 所以这是没有意义的:
比如说,你对一个列表有一个限制。 测试 limit == limit 是没有意义的,测试应该尝试将超过 limit 的元素放入列表中。
OTOH,如果您想确保常量在正确的位置使用(即它应该用作某些 UI 元素的标签),那么使用字符串常量(而不是新的文字)进行测试是有意义的)。
也就是说,对于我自己的 UI 测试,我使用抓取工具来收集所有可见的字符串,并将生成的(长)字符串与文件的内容进行比较。 这是针对 UI 中意外更改的非常简单的包罗万象的测试,最适合 HTML 中的 UI(我下载了 HTML 并进行比较),但相同的模式可以应用于任何 UI。
A different way to express what the others already said: If the test can never fail, there is no point in keeping it. So this would not make sense:
Say, for example, you have a limit for a list. There is no point in testing that limit == limit, the test should try to put more than limit elements into the list.
OTOH, if you want to make sure that the constants is being used in the proper place (i.e. it should be used as the label of some UI element), it makes sense to use the test using the string constant (instead of a new literal).
That said, for my own UI tests, I use scrapers which collect all strings visible and compare the resulting (long) string with the contents of a file. This is a very simple catch-all test for unexpected changes in the UI and works best for UIs in HTML (I download the HTML and compare it) but the same pattern can be applied to any UI.
我暂时会坚持参考。
问题是,如果需求发生变化,应该触发某人更改测试。 可以说,更改测试的正确方法是将其更改为新值作为文字,查看它失败,更改生产静态,查看它通过,然后更改测试以再次使用生产静态并查看它仍然通过。
这有任何意义吗?
I would stick with the reference for the moment.
The thing is, if the requirement changes that should trigger someone changing a test. Arguably the right way to change the test is to change it to the new value as a literal, see it fail, change the production static, see it pass, then change the test to also use the production static again and see it still pass.
Does that make any sense?
我认为你所拥有的很好,是的,这是 DRY 的有效使用:如果这个值将在多个测试中结束,那么如果值发生变化,你不想更改多个测试。 但您还应该添加一项额外的测试,即验证Feature.FEATURE_LABEL 值的测试。
这是应用“一次且仅两次”的好地方:如果您只进行了一次测试,其中测试了 FEATURE_LABEL 的值,那么我只需使用文字字符串。 仅当您有多个使用它的测试时,我才会开始使用参考(并为该值添加测试)。
I think what you have is good, and yes it is a valid use of DRY: if this value is going to end up in several tests you don't want to change several if the value changes. But you should also add an additional test, the one that validates the value of Feature.FEATURE_LABEL.
This is a good place to apply "once and only twice": if you only had a single test where the value of FEATURE_LABEL was tested then I'd just use the literal string. It is only if you have multiple tests using it where I'd start using the reference (and add a test for the value).