Должны ли мы стремиться к DRY, в том смысле, что изменения в функциональности влияют на как можно меньше кода, на нашу предсказуемость, в том смысле, что работа кода тривиальна при написании модульных тестов? По сути, я спрашиваю о компромиссе между созданием вспомогательных методов, которые носят очень общий характер и могут использоваться несколькими модульными тестами, а не только когда ограничивают код тестирования одним модульным тестом. В качестве примера рассмотрим случай фабрики со следующей сигнатурой метода:
public Node buildNode(String path, String name, Map<String, Object> attributes);
В зависимости от предоставленных параметров результирующий объект Node будет отличаться, и поэтому нам необходимо протестировать различные возможности. Если мы стремимся к предсказуемости, мы могли бы написать два автономных модульных теста, как указано в первом примере, но если мы стремимся к DRY, мы бы предпочли добавить общий вспомогательный метод, такой как во втором примере:
EXAMPLE1:
@Test
public void testBuildBasicNode() {
Node node = testee.buildNode("/home/user", "Node", null);
assertEquals("/home/user/Node", node.getAbsolutePath());
assertEquals(false, node.isFolder());
}
@Test
public void testBuildAdvancedNode() {
Map<String, Object> attributes = new HashMap<String, Object>();
attributes.put("type", NodeType.FOLDER);
Node node = testee.buildNode("/home/user", "Node", attributes);
assertEquals("/home/user/Node", node.getAbsolutePath());
assertEquals(true, node.isFolder());
}
EXAMPLE2:
@Test
public void testBuildBasicNode() {
Node node = testee.buildNode("/home/user", "Node", null);
Node comparisonNode = buildComparisonNode("/home/user", "Node", null);
assertEquals(comparisonNode, node);
}
@Test
public void testBuildAdvancedNode() {
Map<String, Object> attributes = new HashMap<String, Object>();
attributes.put("type", NodeType.FOLDER);
Node node = testee.buildNode("/home/user", "Node", attributes);
Node comparisonNode = buildComparisonNode("/home/user", "Node", attributes);
assertEquals(comparisonNode, node);
}
private Node buildComparisonNode(String path, String name, Map<String, Object> attributes) {
// Not just a duplicate of the buildNode method,
// can be more trivial if we only limit it to unit tests that share some common attributes
...
}
Моя проблема с первым примером (предсказуемость) заключается в том, что если какие-либо функциональные возможности меняются (например, скажем, как должен быть отформатирован AbsolutePath), он требует изменений во всех моих модульных тестах. Моя проблема со вторым примером заключается в том, что buildComparisonNode ощущается как нечто, что также должно быть протестировано, и я, конечно, не хочу начинать писать тесты для тестов.
Также, как заключительная мысль, вы бы объявили конечные переменные для литеральных строк, использованных в примерных модульных тестах, или они в порядке, как они есть?