Если у меня есть какой-то код, который покрывает 80% тестов (все тесты пройдены), будет ли справедливо сказать, что он более высокого качества, чем код без тестового покрытия?
Или справедливо сказать, что это более ремонтопригодно?
Если у меня есть какой-то код, который покрывает 80% тестов (все тесты пройдены), будет ли справедливо сказать, что он более высокого качества, чем код без тестового покрытия?
Или справедливо сказать, что это более ремонтопригодно?
Ответы:
В строгом смысле несправедливо предъявлять какие-либо претензии до тех пор, пока не будет установлено качество тестового набора. Прохождение 100% тестов не имеет смысла, если большинство тестов тривиальны или повторяются друг с другом.
Вопрос в том, выявил ли какой-либо из этих тестов в истории проекта ошибки? Цель теста - найти ошибки. И если они этого не сделали, они провалились как тесты. Вместо того чтобы улучшать качество кода, они могут дать вам ложное чувство безопасности.
Чтобы улучшить свои тестовые схемы, вы можете использовать (1) методы белого ящика, (2) методы черного ящика и (3) тестирование мутаций.
(1) Вот несколько хороших техник «белого ящика», которые можно применить к вашим тестам. Тест whitebox создается с учетом конкретного исходного кода. Одним из важных аспектов тестирования белого ящика является покрытие кода:
if
или while
), есть ли у вас тест, который заставляет его быть правдой, а другой, который заставляет его быть ложным? [Охват решения]&&
) или дизъюнкцией (использует ||
), имеет ли каждое подвыражение тест, где оно истинно / ложно? [Условие покрытия]break
из петли покрыт?(2) Методы «черного ящика» используются, когда требования доступны, а сам код - нет. Это может привести к качественным испытаниям:
(3) Наконец, предположим, что у вас уже есть много хороших тестов для освещения белого ящика и применены методы черного ящика. Что еще можно сделать? Пришло время проверить ваши тесты . Одним из методов, который вы можете использовать, является Mutation Testing.
При тестировании на мутации вы вносите изменения в (копию) вашей программы в надежде создать ошибку. Мутация может быть:
Изменить ссылку одной переменной на другую переменную; Вставьте функцию abs (); Менять меньше чем больше чем больше; Удалить заявление; Заменить переменную на постоянную; Удалить переопределяющий метод; Удалить ссылку на супер метод; Изменить порядок аргументов
Создайте несколько десятков мутантов в разных местах вашей программы [программа все равно должна будет скомпилироваться для тестирования]. Если ваши тесты не находят эти ошибки, вам нужно написать тест, который может найти ошибку в мутированной версии вашей программы. Как только тест обнаружит ошибку, вы убили мутанта и можете попробовать другой.
Приложение : Я забыл упомянуть этот эффект: ошибки имеют тенденцию к кластеризации . Это означает, что чем больше ошибок вы найдете в одном модуле, тем выше вероятность, что вы найдете больше ошибок. Итак, если у вас есть тест, который не проходит (то есть тест успешен, так как цель состоит в том, чтобы найти ошибки), вы должны не только исправить ошибку, но и написать больше тестов для модуля, используя методы выше.
Пока вы обнаруживаете ошибки с постоянной скоростью, усилия по тестированию должны продолжаться. Только тогда, когда количество обнаруженных новых ошибок снижается, вы можете быть уверены, что приложили немало усилий для тестирования на этом этапе разработки.
По одному определению это более приемлемо, так как любые критические изменения с большей вероятностью будут обнаружены тестами.
Однако тот факт, что код проходит модульные тесты, не означает, что он по сути более высокого качества. Код все еще может быть плохо отформатирован с нерелевантными комментариями и несоответствующими структурами данных, но он все же может пройти тесты.
Я знаю, какой код я бы предпочел поддерживать и расширять.
Код без каких-либо тестов может быть очень высокого качества, читабельным, красивым и эффективным (или просто мусором), поэтому нет, несправедливо утверждать, что код с 80% охватом тестов имеет более высокое качество, чем код без покрытия тестами.
Было бы справедливо сказать, что 80% кода, покрытого хорошими тестами, вероятно, приемлемого качества и, вероятно, относительно ремонтопригодны. Но это гарантирует мало, правда.
Я бы назвал это более рефактабельным. Рефакторинг становится чрезвычайно простым, если код покрыт множеством тестов.
Было бы справедливо назвать его более ремонтопригодным.
Я бы согласился на ремонтопригодную часть. Майкл Фезерс недавно опубликовал видео о своем великолепном выступлении под названием « Глубокий синергизм между тестируемостью и хорошим дизайном », в котором он обсуждает эту тему. В своем выступлении он говорит, что отношения - это один из способов, то есть хорошо спроектированный код тестируемый, но тестируемый код не обязательно хорошо спроектирован.
Стоит отметить, что потоковое видео в видео невелико, поэтому его стоит загрузить, если вы хотите посмотреть его полностью.
Я задавал себе этот вопрос в течение некоторого времени в связи с «покрытием условий». Так как насчет этой страницы на atollic.com "Почему анализ покрытия кода?"
С технической точки зрения, анализ покрытия кода находит области в вашей программе, которые не охвачены вашими тестовыми примерами, что позволяет вам создавать дополнительные тесты, которые охватывают иные непроверенные части вашей программы. Поэтому важно понимать, что покрытие кода помогает вам понять качество ваших процедур тестирования, а не качество самого кода .
Это, кажется, очень актуально здесь. Если у вас есть набор тестовых примеров, которым удается достичь определенного уровня (кода или иного) покрытия, то вы, скорее всего, вызываете тестируемый код с довольно исчерпывающим набором входных значений! Это не расскажет вам много о тестируемом коде (если код не взорвется или не сгенерирует обнаруживаемые ошибки), но даст вам уверенность в вашем наборе тестовых примеров .
При интересном изменении зрения Necker Cube тестовый код теперь тестируется тестируемым кодом!
Есть много способов гарантировать, что программа делает то, что вы намерены, и гарантировать, что изменения не будут иметь непредвиденных последствий.
Тестирование одно. Избегание мутации данных - еще один. Такова система типов. Или формальная проверка.
Итак, хотя я согласен, что тестирование, как правило, хорошая вещь, данный процент тестирования может не иметь большого значения. Я предпочел бы положиться на что-то написанное на Haskell без тестов, чем на хорошо протестированную библиотеку PHP