Перейти к основному содержимому

Введение в JaCoCo

· 5 мин. чтения

Задача: Наибольшая подстрока без повторений

Для заданной строки s, найдите длину наибольшей подстроки без повторяющихся символов. Подстрока — это непрерывная непустая последовательность символов внутри строки...

ANDROMEDA 42

1. Обзор

Покрытие кодаэто программная метрика , используемая для измерения того, сколько строк нашего кода выполняется во время автоматизированных тестов.

В этом руководстве мы рассмотрим некоторые практические аспекты использования JaCoCo, генератора отчетов о покрытии кода для проектов Java.

2. Конфигурация Maven

Чтобы начать работу с JaCoCo, нам нужно объявить этот плагин maven в нашем файле pom.xml :

<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.7.201606060606</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>

Приведенная здесь ссылка всегда будет вести к последней версии плагина в центральном репозитории maven.

3. Отчеты о покрытии кода

Прежде чем мы начнем рассматривать возможности покрытия кода JaCoCo, нам нужен пример кода. Вот простая функция Java, которая проверяет, читается ли строка одинаково в обоих направлениях:

public boolean isPalindrome(String inputString) {
if (inputString.length() == 0) {
return true;
} else {
char firstChar = inputString.charAt(0);
char lastChar = inputString.charAt(inputString.length() - 1);
String mid = inputString.substring(1, inputString.length() - 1);
return (firstChar == lastChar) && isPalindrome(mid);
}
}

Теперь все, что нам нужно, это простой тест JUnit :

@Test
public void whenEmptyString_thenAccept() {
Palindrome palindromeTester = new Palindrome();
assertTrue(palindromeTester.isPalindrome(""));
}

Запуск теста с помощью JUnit автоматически запустит агент JaCoCo. Он создаст отчет о покрытии в двоичном формате в целевом каталоге target/jacoco.exec.

Очевидно, что мы не можем интерпретировать вывод в одиночку, но другие инструменты и плагины могут, например, Sonar Qube .

Хорошая новость заключается в том, что мы можем использовать цель jacoco:report для создания удобочитаемых отчетов о покрытии кода в нескольких форматах, таких как HTML, CSV и XML.

Например, теперь мы можем взглянуть на страницу target/site/jacoco/index.html , чтобы увидеть, как выглядит сгенерированный отчет:

./2fbc4c24bf2b3924b18392cfc24c4744.png

Перейдя по ссылке, приведенной в отчете, Palindrome.java , мы можем просмотреть более подробное представление для каждого класса Java:

./ef995af3e7a141d554728f300c40cbbe.png

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

4. Анализ отчета

Наш отчет показывает охват инструкций 21%, охват ветвей 17%, цикломатическая сложность 3/5 и так далее.

38 инструкций, показанных JaCoCo в отчете, относятся к инструкциям байт-кода, а не к обычным инструкциям кода Java.

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

  • Красный ромб означает, что ни одна ветвь не выполнялась на этапе тестирования.
  • Желтый ромб показывает, что код закрыт частично — некоторые ответвления не были реализованы.
  • Зеленый ромб означает, что во время теста были задействованы все ветки.

Тот же цветовой код применяется к цвету фона, но для покрытия линий.

JaCoCo в основном предоставляет три важных показателя:

  • Покрытие строк отражает объем кода, который был выполнен на основе количества инструкций байт-кода Java, вызванных тестами.
  • Покрытие переходов показывает процент выполненных переходов в коде, обычно связанных с операторами if/else и switch .
  • Цикломатическая сложность отражает сложность кода, задавая количество путей, необходимых для покрытия всех возможных путей в коде с помощью линейной комбинации.

Возьмем тривиальный пример: если в коде нет операторов if или switch , цикломатическая сложность будет равна 1, так как нам нужен только один путь выполнения, чтобы покрыть весь код.

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

5. Разбивка концепции

JaCoCo работает как агент Java. Он отвечает за инструментирование байт-кода во время выполнения тестов. JaCoCo углубляется в каждую инструкцию и показывает, какие строки выполняются во время каждого теста.

Для сбора данных о покрытии JaCoCo использует ASM для инструментирования кода на лету, получая в процессе события от интерфейса JVM Tool :

./5591b2e316f9fcbba048136a4ec4da9d.png

Также возможно запустить агент JaCoCo в режиме сервера. В этом случае мы можем запустить наши тесты с jacoco:dump в качестве цели, чтобы инициировать запрос дампа.

Мы можем перейти по ссылке официальной документации для получения более подробных сведений о дизайне JaCoCo.

6. Оценка покрытия кода

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

Чтобы достичь 100% покрытия кода, нам нужно ввести тесты, которые покрывают недостающие части, показанные в исходном отчете:

@Test
public void whenPalindrom_thenAccept() {
Palindrome palindromeTester = new Palindrome();
assertTrue(palindromeTester.isPalindrome("noon"));
}

@Test
public void whenNearPalindrom_thanReject(){
Palindrome palindromeTester = new Palindrome();
assertFalse(palindromeTester.isPalindrome("neon"));
}

Теперь у нас достаточно тестов, чтобы покрыть весь наш код, но чтобы убедиться в этом, давайте запустим команду Maven mvn jacoco:report , чтобы опубликовать отчет о покрытии:

./4498e9445e2e069f7005d3e4c466e5a1.png

Как мы видим, все строки/ветви/пути в нашем коде полностью покрыты:

./93215d45cc4d1461d95ba7cc8bf17d98.png

В реальном проекте, по мере развития, нам необходимо отслеживать показатель покрытия кода.

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

Мы можем сделать это, добавив следующую цель проверки в наш файл pom.xml :

<execution>
<id>jacoco-check</id>
<goals>
<goal>check</goal>
</goals>
<configuration>
<rules>
<rule>
<element>PACKAGE</element>
<limits>
<limit>
<counter>LINE</counter>
<value>COVEREDRATIO</value>
<minimum>0.50</minimum>
</limit>
</limits>
</rule>
</rules>
</configuration>
</execution>

Как мы видим, мы ограничиваем минимальную оценку покрытия строк до 50%.

Цель jacoco:check связана с verify , поэтому мы можем запустить команду Maven mvn clean verify , чтобы проверить , соблюдаются ли правила или нет. Журналы будут показывать что-то вроде: ``

[ERROR] Failed to execute goal org.jacoco:jacoco-maven-plugin:0.7.7.201606060606:check 
(jacoco-check) on project mutation-testing: Coverage checks have not been met.

7. Заключение

В этой статье мы узнали, как использовать плагин JaCoCo maven для создания отчетов о покрытии кода для проектов Java.

Имейте в виду, однако, что 100-процентное покрытие кода не обязательно отражает эффективность тестирования , поскольку оно отражает только объем кода, который использовался во время тестов. В предыдущей статье мы говорили о мутационном тестировании как о более сложном способе отслеживания эффективности тестов по сравнению с обычным покрытием кода .

Пример, представленный в этой статье, доступен в проекте GitHub .