Я работаю инженером DevOps в крупном общедоступном приложении, которое имеет около 90+ микросервисов (на основе Java). Мы постоянно сталкиваемся со сценариями, которые мы обнаруживаем в полевых условиях, которые не были зафиксированы ни в одном из наших испытаний. Несмотря на улучшение наших стратегий тестирования и оценки покрытия кода, мы не смогли оценить «силу» наших тестовых случаев.
Мы искали варианты и решения, которые могли бы помочь нам быть более уверенными в наших тестовых примерах и коде, который мы разрабатываем. Как инженер DevOps, моя обязанность заключалась в том, чтобы определить варианты и опробовать их, чтобы решить эту проблему и включить ее в процесс автоматизированной сборки.
Мы столкнулись с подходом мутационного тестирования, который предлагал ответы на вопросы / проблемы, которые у нас были вокруг наших тестовых случаев. Я был склонен попробовать этот подход, чтобы помочь разработчикам написать более конкретные тестовые примеры, и, как только я это подтвердил, я мог использовать его как часть процесса сборки, чтобы сделать его полностью автоматизированным.
Вам также может понравиться: Mutation Testing: покрытие вашего кода правильными тестовыми примерами
Традиционные подходы к покрытию тестами имеют недостаток, поскольку они проверяют только код, выполняемый тестовыми примерами, и показывают код, который не охватывается. Они не помогают нам оценивать или идентифицировать скрытые проблемы в коде. Мутация позволяет разработчикам писать сильные случаи (а не просто указывать, был ли выполнен код во время выполнения тестовых случаев) и по сути обеспечивает тщательный тест кода.
Учитывая, что у нас есть стек технологий Java, нам пришлось рассмотреть соответствующие варианты, которые помогут нам провести тестирование и анализ мутаций в нашей экосистеме. PIT оказался наиболее жизнеспособным вариантом, основанным на наших основных потребностях.
Я попытался просмотреть концепции, которые я понял, и ключевые аспекты, которые я обнаружил в этом путешествии. Некоторые из самых больших задач заключались в том, чтобы донести это до наших разработчиков, успешно включить PIT Mutation Testing в нашей экосистеме и включить его в процесс сборки. Я суммирую свои знания и проблемы, с которыми мы столкнулись в этом путешествии: я надеюсь помочь моим коллегам-инженерам.
Я начинаю с некоторых основ о тестировании мутаций; Вы можете найти эти данные в открытом доступе на разных сайтах / порталах.
Что такое мутация?
При тестировании на мутацию мы модифицируем наш исходный код и запускаем тестовые примеры для нашего кода. Эти модификации исходного кода называются мутантами. Предположим, если вы написали (x> y) в своем коде, мутантом этого может быть код с (x <y).
Как только код мутанта запускается против ваших тестовых случаев, если он выживает (проходит тестовые случаи), он становится частью выживших мутантов. Если мутант терпит неудачу во время выполнения ваших тестовых случаев, он становится частью убитых мутантов. Чем больше убитых мутантов, тем сильнее ваши тесты.
Причина запуска мутаций — написать конкретные тестовые сценарии, которые должны убить мутанта.
Типы мутационного тестирования
Тестирование на мутации можно разделить на три категории: мутация значения, мутация решения и мутация оператора.
Значение Мутация
Он изменяет значение в исходном коде для обнаружения ошибок.
Пример: if(x=)
заменить x на что-то отличное от 20.
Решение Мутации
Они изменяют решения / условия для проверки ваших случаев на предмет ошибок проектирования.
Пример: if ( ), изменить объект на NullnewResponse
instanceof
ErrorResponse
newResponse
Мутации
операторов Это изменяет оператор, удаляя или добавляя одну и ту же строку, чтобы проверить, скопировал ли разработчик код и вставил его.
Оценка мутации
Оценка мутаций — это единица, которая определяет, насколько силен / эффективен ваш анализ мутаций. Он определяется как:
Оценка мутации = (убитые мутанты / общее количество мутантов) * 100
Включение PIT с вашим исходным кодом Java
Существует несколько решений, которые могут включить анализ мутаций в вашем коде Java. Однако в этой статье мы рассмотрим инструмент PIT, чтобы включить тестирование мутаций. PIT быстрее и проще в использовании по сравнению с другими инструментами. Кроме того, он активно развивается и поддерживается.
Обратитесь к странице Github для PIT .
Мутаторы в Яме
В настоящее время PIT предоставляет несколько встроенных мутаторов, большинство из которых активированы по умолчанию. Набор по умолчанию может быть переопределен, и могут быть выбраны различные операторы, минуя имена необходимых операторов для параметра мутаторов .
Мутаторы по умолчанию
Условный граничный мутатор — заменяет реляционные операторы <, <=,>,> =
Инкременты Mutator — заменить инкременты на декременты и наоборот.
Invert Negatives Mutator — инвертирует отрицание целого числа и числа с плавающей точкой.
Math Mutator — заменяет двоичные арифметические операции для целочисленных или арифметических операций с плавающей точкой другими операциями.
Отклонить условный мутатор — отменить условные проверки.
Возвращаемые значения мутаторного — мутирует в возвращаемых значениях вызова метода в зависимости от типа возвращаемого значения методы. Для типа возвращаемого объекта, изменяется на ноль .
Void Method Calls Mutator — удаляет вызовы методов для void методов.
Мутаторы не по умолчанию
Конструктор вызовов мутаторный — заменяет конструктор вызовов с нулем .
Inline Constant Mutator — изменяет встроенные константы и заменяет значения по умолчанию в зависимости от типа данных.
Вызовы методов без Void Mutator — удаляет вызовы методов для не void методов, и их возвращаемое значение заменяется значением Java по умолчанию для этого конкретного типа.
Remove Conditionals Mutator — удалить все условные операторы, чтобы всегда выполнялись защищенные операторы.
Мутатор переменных-членов (экспериментальный) — удаление назначений переменных-членов, а также конечных членов.
Switch Mutator (Experimental) — изменяет оператор switch, заменяя метку по умолчанию.
Настройка PIT
Настройте PIT плагин в вашей IDE
Вы можете перейти на рынок Eclipse, скачать плагин PIT и запустить мутационные тесты.
Включение Pit для вашего Java-кода
1. Добавить зависимость
Вам нужно добавить зависимость для pitest в pox.xml , чтобы загрузить jeste jar.
XML
xxxxxxxxxx
1
<dependency>
2
<groupId>org.pitest</groupId>
3
<artifactId>pitest</artifactId>
4
<version>1.4.0</version>
5
</dependency>
2. Настройте плагин PIT
Как только зависимость добавлена, нам нужно настроить конфигурацию плагина pitest. Следующий фрагмент из файла pom.xml является примером настройки плагина pitest:
XML
xxxxxxxxxx
1
<plugin>
2
<groupId>org.pitest</groupId>
3
<artifactId>pitest-maven</artifactId>
4
<version>1.4.0</version>
5
<configuration>
6
<outputFormats>
7
<outputFormat>XML</outputFormat>
8
<outputFormat>HTML</outputFormat>
9
</outputFormats>
10
<avoidCallsTo>
11
<avoidCallsTo>org.apache.log4j.*</avoidCallsTo>
12
<avoidCallsTo>org.slf4j.*</avoidCallsTo>
13
</avoidCallsTo>
14
<targetClasses>
15
<param>com.project.*</param>
16
<param>com.project.*</param>
17
</targetClasses>
18
<targetTests>
19
<param>com.projecttest.*</param>
20
</targetTests>
21
<threads>4</threads>
22
<historyInputLocation>target/pitHistory.txt</historyInputLocation>
23
<historyOutputLocation>target/pitHistory.txt</historyOutputLocation>
24
<timestampedReports>false</timestampedReports>
25
</configuration>
26
</plugin>
ПРИМЕЧАНИЕ . Пожалуйста, добавьте конфигурацию плагина под тегом PLUGIN MANAGEMENT ; добавление его в другом месте приведет к ошибкам.
3. Конфигурация плагина в деталях:
Обновите следующее в конфигурации, основываясь на информации о пакете вашего проекта.
Примечание. Внутри целевых классов требуются только пакеты, в которых вы хотите включить анализ мутаций. Обновите список пакетов и классов, которые вы хотите рассмотреть для области мутации.
XML
xxxxxxxxxx
1
<targetClasses>
2
<param>com.project.*</param>
3
<param>com.project.*</param>
4
</targetClasses>
Примечание. Внутри целевых тестов требуются только те тестовые случаи, в которых вы хотите запустить мутационное тестирование. Список глобусов тестовых классов и / или пакетов будет использоваться Pitest для проверки мутации.
XML
xxxxxxxxxx
1
<targetTests>
2
<param>com.projecttest.*</param>
3
</targetTests>
Избегайте звонков на:
Список пакетов и классов, которые рассматриваются вне области мутации. Любые строки кода, содержащие вызовы этих классов, не будут видоизменяться.
XML
xxxxxxxxxx
1
<avoidCallsTo>
2
<avoidCallsTo>org.apache.log4j.*</avoidCallsTo>
3
<avoidCallsTo>org.slf4j.*</avoidCallsTo>
4
</avoidCallsTo>
4. Дополнительные настройки плагина в деталях
Выходные форматы:
Список форматов для записи результатов мутации после анализа мутаций. Отчеты HTML и XML необходимы для SonarQube для генерации деталей мутации. (Если вы планируете отправить результаты теста в Sonarqube, как процесс проверки качества.)
XML
xxxxxxxxxx
1
<outputFormats>
2
<outputFormat>XML</outputFormat>
3
<outputFormat>HTML</outputFormat>
4
</outputFormats>
История:
Перейдите к файлу, содержащему информацию истории для инкрементального анализа, чтобы ускорить тестирование мутаций.
XML
xxxxxxxxxx
1
<historyInputLocation>target/pitHistory.txt</historyInputLocation>
2
<historyOutputLocation>target/pitHistory.txt</historyOutputLocation>
Мутаторы:
Список операторов мутации, применяемых для тестирования мутаций. Если не дано, мутационный тест будет продолжен с мутаторами по умолчанию.
XML
xxxxxxxxxx
1
<mutators>
2
<mutator>CONSTRUCTOR_CALLS</mutator>
3
<mutator>NON_VOID_METHOD_CALLS</mutator>
4
</mutators>
Потоки
Количество потоков, используемых при тестировании мутаций. По умолчанию будет использоваться один поток.
XML
xxxxxxxxxx
1
<threads>5</threads>
Выполнение анализа мутаций:
Выполните следующую команду, чтобы сгенерировать отчеты анализа мутаций:
Оболочка
xxxxxxxxxx
1
clean test verify org.pitest:pitest-maven:mutationCoverage
Эта команда создаст папку pit-reports внутри цели. Зайдите в папку pit-reports и откройте файл index.html . Это даст вам подробности анализа мутаций.
-
Отчеты, подготовленные PIT, представлены в удобном для чтения формате, сочетающем в себе покрытие линий и информацию об охвате мутаций. Для получения хорошего результата мутации рекомендуется запустить проект с охватом линий не менее 80-90%.
Нажмите на основной класс, чтобы проверить отчеты — светло-зеленый показывает охват линий, а темно-зеленый показывает охват мутаций. Вы также можете увидеть, какие мутации выполняются в конкретном блоке кода.
Детали убитой / выжившей мутации показаны относительно соответствующего числа.
Пример фрагмента взят из отчета о покрытии тестового проекта .
В отчете светло-розовый будет показывать отсутствие покрытия линий, а темно-розовый — отсутствие мутации.
Отправка отчетов в сонар
Sonarqube также предлагает несколько плагинов для анализа ямы в своих воротах качества. С их помощью вы можете установить правила для ваших качественных ворот на основе количества мутантов, убитых мутантов, выживших мутантов и охвата мутациями.
Обратитесь к следующим ссылкам для плагинов Pit в Sonar:
Интеграция с SONAR и Jenkins для качества ворот
Для интеграции анализа мутаций с Sonar вы можете загрузить следующие плагины в свой Sonar и добавить правила в свои ворота качества.
После загрузки плагина вам необходимо добавить правила в ваш профиль качества по умолчанию. Когда правила находятся в профиле качества по умолчанию, вы можете настроить шлюз качества и включить шлюз качества в конвейере сборки, поэтому, если статус шлюза качества является ошибкой, сборка должна завершиться неудачей.
Вывод
Использование Pit решило множество проблем в нашем коде. Наши тестовые наборы стали более конкретными, и мы стали больше фокусироваться на прочности тестового набора, а также на тестовом покрытии. Наши тесты теперь больше сосредоточены на тестировании логики кода, а не только на тестовом покрытии. Это помогло нам исправить ошибки и улучшить время сборки.
Однако были некоторые проблемы. Например, настройка PIT и изменение наших тестов были немного трудоемкими. Кроме того, работа по сборке теперь занимает немного больше времени по сравнению с нашим предыдущим процессом. Мы улучшили это с течением времени с помощью инкрементального анализа.
Со стороны разработчиков, они должны были сосредоточиться на том, какой класс они хотели бы запустить мутацию, используя какие тестовые случаи. Кроме того, они должны были выбрать тип мутатора для основы функциональности.
Дальнейшее чтение
Мутационное тестирование: покрытие вашего кода правильными тестовыми примерами (часть 2) .