Мне интересно, не устарели ли измерения покрытия условного кода текущими инструментами для Java после появления Java 8? С Java 8 - х Optional
и Stream
часто мы можем избежать кода ветвь / петлю, что делает его легко получить очень высокое условное покрытие без проверки всех возможных путей выполнения. Давайте сравним старый код Java с кодом Java 8:
До Java 8:
public String getName(User user) {
if (user != null) {
if (user.getName() != null) {
return user.getName();
}
}
return "unknown";
}
В вышеуказанном методе есть 3 возможных пути выполнения. Чтобы получить 100% условного покрытия, нам нужно создать 3 модульных теста.
Java 8:
public String getName(User user) {
return Optional.ofNullable(user)
.map(User::getName)
.orElse("unknown");
}
В этом случае ветви скрыты, и нам нужно только 1 тест, чтобы получить 100% охват, и не имеет значения, в каком случае мы будем тестировать. Хотя есть все те же 3 логические ветви, которые должны быть рассмотрены, я считаю. Я думаю, что это делает статистику условного покрытия совершенно ненадежной в наши дни.
Имеет ли смысл измерять условное покрытие для кода Java 8? Существуют ли какие-либо другие инструменты, обнаруживающие проверенный код?
источник
getName
? Похоже, что еслиuser
null, он должен вернуть «unknown». Еслиuser
не ноль иuser.getName()
нуль, он должен вернуть «неизвестно». Еслиuser
не ноль иuser.getName()
не нуль, он должен вернуть это. Таким образом, вы бы протестировали эти три случая, потому что это контрактgetName
. Вы, кажется, делаете это задом наперед. Вы не хотите видеть ветки и писать тесты в соответствии с ними, вы хотите писать свои тесты в соответствии с вашим контрактом и гарантировать, что контракт выполнен. Это когда у вас есть хорошее освещение.Ответы:
Я не знаю ни о чем. Я попытался запустить код, который вы имеете через JaCoCo (он же EclEmma), просто чтобы быть уверенным, но он показывает 0 ветвей в
Optional
версии. Я не знаю ни одного способа его настройки, чтобы сказать иначе. Если вы сконфигурируете его также для включения файлов JDK, теоретически в нем будут отображаться ветвиOptional
, но я думаю, что начинать проверку кода JDK было бы глупо. Вы просто должны предположить, что это правильно.Тем не менее, я думаю, что основная проблема заключается в понимании того, что дополнительные ветви, которые у вас были до Java 8, были, в некотором смысле, искусственно созданными ветвями. То, что они больше не существуют в Java 8, означает, что теперь у вас есть подходящий инструмент для работы (в данном случае,
Optional
). В коде до Java 8 вам приходилось писать дополнительные модульные тесты, чтобы вы могли быть уверены, что каждая ветвь кода ведет себя приемлемым образом - и это становится немного более важным в разделах кода, которые не являются тривиальными, какUser
/getName
пример.В коде Java 8 вы вместо этого доверяете JDK, что код работает правильно. Таким образом, вы должны обрабатывать эту
Optional
строку так же, как это делают инструменты покрытия кода: 3 строки с 0 ветвями. То, что в приведенном ниже коде есть другие строки и ветви, - это то, на что вы просто не обращали внимания прежде, но существовали каждый раз, когда вы использовали что-то вродеArrayList
илиHashMap
.источник
if
иnull
по-прежнему является частью языка ;-) Все еще возможно писать код по-старому и передаватьnull
пользователь или пользователь сnull
именем. Ваши тесты должны просто доказать, что контракт выполняется независимо от того, как метод реализован. Дело в том, что нет никакого инструмента, чтобы сказать вам, полностью ли вы протестировали контракт.Optional
(и связанные методы) работают, вам больше не нужно их проверять. Не так, как вы проверялиif-else
: каждыйif
был потенциальным минным полем.Optional
и подобные функциональные идиомы уже закодированы и гарантированно не сбивают вас с толку, так что по сути есть «ветвь», которая исчезла.Optional
. Как он сказал, логически мы все равно должны тестировать, которыйgetName()
обрабатывает различные возможные входные данные так, как мы намереваемся, независимо от его реализации. Труднее определить это без помощи инструментов покрытия кода, как это было бы до JDK8.if-else
потому что каждая из этих конструкций является полностью произвольной. В отличие от этого ,Optional
,orElse
,map
и т.д., все уже протестировали. По сути, ветви «исчезают», когда вы используете более мощные идиомы.