- PVSM.RU - https://www.pvsm.ru -
Многие из вас, возможно, слышали про Mutation Testing в замечательном подкасте «Разбор полётов» [1] или читали в википедии [2]. Для тех, кто всё-таки с понятием пока не знаком, в двух словах объясню.
Мутационное тестирование — альтернативный подход к измерению качества ваших тестов. Вместо того, чтобы считать банальный code coverage, используется более разумный механизм. В байт-код ваших классов внедряются случайные изменения, иначе называемые мутациями. Если после такой мутации не упал ни один тест, который покрывает внесённые изменения, то велика вероятность того, что с тестами у вас не особо-то и хорошо. Пример возможной мутации:
Было: |
|
Стало: |
|
Изменение довольно критичное, потому тест, покрывающий этот блок кода, наверняка должен упасть. Под катом я расскажу о весьма хорошей библиотеке Pitest [3], покажу, как её подключить к своему проекту, и приведу результаты тестирования на реальном коде.
Начнём с простого проекта[github [4]], содержащего один-единственный класс:
|
|
и тест на него:
|
|
Для того, чтобы подключить pitest, достаточно добавить его плагин в maven:
|
|
Чуть подробнее по конфигурации: inScopeClasses
определяет те классы, в которых следует искать тесты и классы, которые следует подвергать мутации. targetClasses
определяет те классы, которые следует подвергнуть только мутации. Кроме того, есть ещё некоторые опции, полный список которых можно посмотреть тут [5].
Если вы по какой-то причине не используете maven, то ещё не всё пропало: можно пользоваться и из командной строки, руководство доступно тут [6].
А чтобы обрести счастье, используя maven, достаточно выполнить команду:
|
В результате проверки мы получим довольно-таки большую простыню логов. Читать её не особо удобно, но зато в папке target/pit-reports/%TIMESTAMP%
генерируется и html-отчёт, похожий на code coverage. В нашем случае интересная его часть будет выглядеть примерно так:
Цифра три возле строки 14 тут означает, сколько мутаций было к этой строчке применено. Далее в разделе mutations для каждой строчки описывается, какие были применены мутации, и каков был результат.
На данный момент есть всего 11 мутаций. Зелёным выделены те, которые включены по умолчанию.
<
превратится в <=
==
превратится в !=
42
будет подставлено 43
, а вместо true
будет подставлено false
false
, 0
, null
)Детальное описание различных типов мутаций доступно на официальном сайте [7].
Получается, что в нашем sample-проекте мутации были в условии (2 шт) и в возвращаемом значении. Попробуем теперь добиться большего количества мутаций. Перепишем сам класс так:
|
|
Но вот в тестах новую функциональность тестировать не будем:
|
|
При запуске code coverage никаких проблем выявлено не будет. А вот если мы запустим mutation testing, то нас быстро схватят за руку и скажут: а функциональность-то не протестирована!
Успех! Теперь мы довольно точно можем сказать, какой код действительно протестирован, а какой нет, и всякие «якобы» тесты, которые на самом деле ничего не проверяют, быстро будут обнаружены.
Идея мутационного тестирования, вообще говоря, не нова, и несколько библиотек уже существовало. Наиболее примечательные из них — Javalanche [8] и Jumble [9]. Однако и они, и другие библиотеки не особо активно развиваются, некоторые из них тормозны и глючны, и практически не имеют интеграции с системами сборки и другими библиотеками. Подробное сравнение доступно тут [10].
Для пущей интересности правильно было бы на каком-нибудь реальном проекте продемонстрировать, как mutation testing находит проблемы, которые не находит code coverage. Отлично для этого подойдёт cobertura — утилита, считающая code coverage. Её отчёт может быть найден в полном виде тут [11], а я приведу лишь маленький кусочек. Чтобы его получить, пришлось немного попотеть с добавлением поддержки maven в исходники и подождать минут двадцать, пока будет идти мутационное тестирование.. Результат получился таким.
Cobertura показывает, что всё хорошо: |
Pitest срывает покровы: |
Итого, подход классный, и явно гораздо более точно оценивает качество тестов, чем code coverage. Конечно, такие проверки и работают существенно дольше, чем обычный coverage, и потому на больших проектах могут занимать часы. Кроме того, сама библиотека Pitest пока несколько сыровата. Например, нет возможности проводить тестирование в несколько потоков, или обязательно успешное выполнение всех тестов без мутаций. Проект, впрочем, opensource [12], и весьма активно развивается, так что я полагаю, что через какое-то время можно будет начать думать о том, чтобы использовать его всерьёз.
Жду ваших вопросов, замечаний и исправлений в комментариях!
Автор: gvsmirnov
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/java/3016
Ссылки в тексте:
[1] «Разбор полётов»: http://habrahabr.ru/blogs/java/137658
[2] википедии: http://en.wikipedia.org/wiki/Mutation_testing
[3] Pitest: http://pitest.org/
[4] github: https://github.com/gvsmirnov/pitest-sample
[5] тут: http://pitest.org/quickstart/maven/#other-options
[6] тут: http://pitest.org/quickstart/commandline/
[7] на официальном сайте: http://pitest.org/quickstart/mutators/
[8] Javalanche: http://www.st.cs.uni-saarland.de/mutation/
[9] Jumble: http://jumble.sourceforge.net/
[10] тут: http://pitest.org/java_mutation_testing_systems/
[11] тут: http://cobertura.sourceforge.net/sample/
[12] opensource: http://code.google.com/p/pitestrunner/
Нажмите здесь для печати.