Использование мутационного тестирования в устаревших проектах

Вы опытный инженер, ваши навыки проверены, и вам доверяют сложную задачу — выполнение некоторых важных работ по обслуживанию устаревшей службы, о которой вы ничего не знаете.

Первоначальные разработчики сервиса давно ушли, у вас достаточно бизнес-контекста для того, что он делает, но ограниченный контекст для технической реализации сервиса.

Просто понять архитектуру и код проекта достаточно сложно, но вам нужно выяснить, как протестировать изменение, а затем оценить его риск и выполнить оценку усилий, основанную на очень небольшом контексте и знаниях.

Разве не было бы замечательно иметь способ уменьшить неизвестность и соответствующие риски, которые с этим связаны?

В этом посте я расскажу о шаблоне, который показался мне полезным при адаптации незнакомой кодовой базы (не обязательно устаревшей), который довольно хорошо работает для повышения уверенности перед началом фактической фазы кодирования.

Проблемы с адаптацией к устаревшим проектам

Одной из самых больших проблем с незнакомыми кодовыми базами является отсутствие контекста — отсутствие «общих знаний», которые были собраны разработчиками кода во время работы над ним, например:

  • какие сложные части кода
  • все эти "косяки"
  • Почему некоторые дизайнерские решения и шаблоны
  • Знание того, какие функции были разработаны под давлением и им не хватает тестового покрытия и качества кода, а какие были разработаны по лучшим шаблонам.

По крайней мере, для меня, когда я начинаю внедрять новую кодовую базу, я начинаю с краткого изучения производственной среды, чтобы понять движущиеся части.

Затем я иду читать основные потоки кода (те, которые имеют отношение к моему изменению).

Затем я просматриваю тесты, чтобы получить общее представление об их качестве, и, просматривая их, запускаю их. Надеемся, что набор тестов станет зеленым ✅.

К счастью, они прошли тест! Но что именно они тестируют? Они чего-нибудь стоят? Будут ли мои изменения обнаружены существующим набором тестов?

Как было бы здорово, если бы вы знали, что код, который вы собираетесь изменить, проходит тщательное тестирование! Что любое изменение, которое вы сделаете, не пройдет тест, и у вас будет утверждение, которое покажет вам влияние вашего изменения? Насколько безопасно вы будете чувствовать себя? Насколько проще будет оценка времени для этого проекта?

Что, если я скажу вам, что вы можете!

Вы можете оценить, насколько хорошо код, к которому вы собираетесь прикоснуться, покрыт тестами? Разве это не было бы здорово?

Кратко о тестировании мутаций

В двух словах, мутационное тестирование — это действие по внесению небольших изменений в программу и подтверждение того, что набор тестов программы улавливает эти изменения, то есть для каждого изменения по крайней мере один тест не пройден.

Вот несколько примеров того, что представляют собой эти «небольшие изменения», называемые «мутантами»:

Изменение условий ветвления — если в коде есть if x < 10, мутант может быть if x > 10 или if True.

Изменение литералов — изменение значений литералов, таких как строки/целые числа/логические значения, поэтому, если ваш код x = 2; return x * 10;, мутант может быть x = 10; return x * 10;

Реальный пример на Scala из проекта stryker-mutator:

Бирюзовый кружок — это реальная мутация, которая была применена к коду — замена s.trim.nonEmpty строки 13 на s.trim.isEmpty.

На мой взгляд, запуская мутационное тестирование кодовой базы, вы получаете две вещи:

  • Понимание, в каких частях кода не хватает тестового покрытия или качества тестирования
  • «ощущение» того, насколько безопасно вносить изменения в программу

Использование мутационного тестирования для анализа слепых зон

Вступление к этому посту случилось со мной — мне поручили внести изменение в систему, с которой я не очень хорошо был знаком.

У него был, казалось бы, неплохой набор тестов из нескольких сотен модульных тестов, но их качество мне было неизвестно, и после первоначального просмотра их кода я боялся, что они недостаточно хороши — они, кажется, делают много вещей, с довольно длинными тестами, которые, как я знаю по опыту, являются запахом кода и красным флажком ошибки 🚩.

Я искал способ оценить, покрываются ли изменения, которые я собираюсь внести, набором тестов. Похоже на то, что мутационное тестирование не обещает?

По счастливой случайности я наткнулся на проект страйкер-мутатор как раз в тот момент, когда собирался приступить к работе. Примерно через 10 минут настройки у меня был HTML-отчет обо всех изменениях, внесенных в мою кодовую базу, которые не удалось уловить существующим набором тестов.

Или проще говоря — он показал мне, какие части кодовой базы недостаточно хорошо покрыты тестами — он пролил очень яркий свет на то, где его применение будет сложным, рискованным и трудоемким. изменения.

Предостережения

Не все идеально, когда я выполнял тесты, многие из мутантов, которые не были пойманы набором тестов, были нефункциональными требованиями, которые обычно не проверяются — например:

  • Мутанты, изменившие лог-сообщения — мы их не тестируем.
  • Мутанты, которые изменили значения метрик мониторинга, например, увеличили счетчик запросов на 2 вместо 1 — для них у нас нет тестов.

Таким образом, хотя первоначальный отчет имел довольно низкое отношение сигнал-шум, настроив тест так, чтобы, например, не изменять строковые литералы, я смог получить лучшие результаты, которые действительно были действенными.

Кроме того — тестируемые мутанты явно не покрывают 100% возможных изменений, поэтому «зеленое» исполнение не гарантирует безопасность изменений, а «красное» исполнение — это определенное проблемное место, где изменения в код нужно вносить осторожно.

Разве тестового покрытия недостаточно?

Вы правы, думая, что покрытие может дать вам аналогичную информацию, НО — покрытие проверяет только то, выполняет ли тест «шаги» на пути кода, он не проверяет, приведет ли изменение этого пути к поломке теста — таким образом, это может создать ложное чувство безопасности. По моему опыту, действительно, высокий уровень охвата ни о чем не свидетельствует.

Последние мысли

Освоиться в незнакомой кодовой базе всегда сложно, не говоря уже о устаревшей кодовой базе.

Запуск набора тестов на мутации при подключении к проекту может действительно облегчить процесс!

Это может пролить свет на проблемные части кодовой базы.
Это может служить предупреждающим знаком, где вы должны быть более осторожными при внесении изменений в код, а где потребуются дополнительные тесты.

Как всегда, мысли и комментарии приветствуются в твиттере @cherkaskyb.