Информации по мутационному тестированию в сети довольно мало. Этому есть простое, на мой взгляд объяснение - в большинстве проектов поле автоматизации тестирования настолько непахано, что сколько бы людей там не работало, всегда будет чем заняться.
Противники измерения покрытия кода утверждают, что эта метрика ничего не говорит о том, насколько хороши написанные тесты. Чтобы понять, что такое хороший тест, давай сначала определимся с тем, что такое тест. Тест - это сравнение тестируемой системы с её упрощенным представлением - моделью. Чем более детальная модель, тем больше наши тесты зависят от деталей реализации системы, тем меньше изменений пройдут незамеченными и тем сложнее её поддерживать. Вырожденный случай - когда тест полностью воспроизводит функцию системы. Чем менее детальная модель, тем легче её поддерживать и тем больше изменений пройдут незамеченными. Вырожденный случай - пустая модель (отсутствие теста). Итак, хороший тест моделирует систему таким образом, что, с одной стороны, фиксирует все значимые (для потребителя) изменения, а с другой стороны - позволяет менять реализацию без изменений в тесте. Если хорошенько подумать над последней фразой, становится ясно, что нельзя написать хороший тест для плохого кода (но это совершенно другая история).
Теперь давай вернёмся к нашему коду и тестам. Чтобы понять, хороши ли наши тесты, нужно выяснить, сломаются ли наши тесты, если изменить поведение системы. Заниматься этим вручную никто не будет по ряду причин, в основном из-за того, что потребуется много времени - сначала выяснить, как должна вести себя система в определённых условиях, затем придумать, как поменять это поведение, внести изменения и выполнить тесты. Совсем другое дело, когда всё это можно сделать автоматически. Как и у большинства автоматических инструментов, результат будет не настолько хорош, как при ручном анализе, но в нашем случае сойдёт =).
Инструменты для мутационного тестирования работают примерно по одной и той же схеме:
- генерируется изменение (мутация) в критически важном месте программы. Типичные мутации - инвертирование условия, изменение граничных условий цикла, замена математических операций и т.п.
- запускаются все тесты (или часть из них, в зависимости от того, насколько умный инструмент)
- анализируются результаты. Если хотя бы один тест упал или сломался - мутант считается убитым, если все тесты зелёные - выжившим
К моему удивлению, инструментов для мутационного тестирования мало. Изначально я хотел провести эксперимент на NodeJS проекте, и нашёл только 1(!) решение, что, в общем-то неслыханно в javascript-мире :). Этим тулом оказался Stryker, но и он в итоге не заработал, т.к. не поддерживает используемый в проекте ES6-синтакс. В итоге я взял другой проект, написаный на старой-доброй Java и запустил мутационное тестирование с использованием фреймворка Pitest.
Ну и теперь самое интересное - результаты и мои выводы:
-
Большинство мутантов выжило в непокрытом коде. Поэтому даже не думай о мутационном тестировании если у тебя нет приличного покрытия. Что такое приличное покрытие - сложно сказать в общем случае, давай для простоты считать что это больше 80% для покрытия строк и близко к 100% для покрытия условий.
-
Величина покрытия не отражает качество тестов. Были как полностью покрытые классы, в которых мутанты выживали, так и не полностью покрытые, в которых мутанты не выживали. Но это единичные случаи, которые можно считать исключениями из п. 1.
-
Время выполнения нелинейно растёт с размером проекта. С ростом кодовой базы растёт как число возможных мутаций, так и число тестов, которые нужно выполнить для каждой мутации. В моём случае (проект среднего размера), юнит-тесты проходили за 10 секунд, а мутационное тестирование заняло около 10 минут.
Обдумывая всё это, я пришёл к интересному выводу: невозможно получить высокое покрытие, имея плохие тесты. Их поддержка будет отнимать слишком много времени, и они либо будут переписаны, либо выброшены. А значит, на проектах с высоким покрытием нет особого смысла запускать мутационное тестирование. Как нет смысла запускать его и на проектах с низким покрытием. Получается, мутационное тестирование никому не нужно? Возможно поэтому нет ни информации, ни разнообразия тулов в этой области?
comments powered by Disqus