Покрытие тестами с JaCoCo
Покрытие (coverage) показывает, какие строки и ветви кода выполнялись во время тестов. Оно отвечает на вопрос «чего мои тесты не коснулись вовсе?». Стандартный инструмент для Java — JaCoCo: он подключается к тестовой JVM, записывает выполненный код и строит отчёт.
Подключение JaCoCo
Добавьте плагин в build/plugins файла pom.xml:
<!-- pom.xml -->
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.15</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>prepare-agent перед тестами записывает Java-агент JaCoCo в свойство argLine. Surefire подхватывает его через @{argLine} в своей настройке — поэтому в уроке про Mockito стоял @{argLine}, а не просто значение. report строит отчёт сразу после тестов.
Запуск
mvn testПосле обычного вывода тестов Maven печатает:
[INFO] Tests run: 60, Failures: 0, Errors: 0, Skipped: 2
[INFO]
[INFO] --- jacoco:0.8.15:report (report) @ blog ---
[INFO] Loading execution data file ...\target\jacoco.exec
[INFO] Analyzed bundle 'blog' with 7 classes
[INFO] BUILD SUCCESSОткройте target/site/jacoco/index.html в браузере. В отчёте таблица по пакетам и классам; щелчок по классу показывает его исходный код с подсвеченными строками:
| Цвет | Смысл |
|---|---|
| Зелёный | Строка выполнялась |
| Жёлтый | Выполнились только некоторые ветви условия |
| Красный | Строка не выполнялась ни разу |
Что показал отчёт
Для проекта курса отчёт нашёл два пробела. В InMemoryPostRepository метод deleteById красный — его не вызывает ни один тест. В PriceCalculator строка if (percent < 0 || percent > 100) жёлтая: тест на 120% есть, а на отрицательную скидку — нет. Обе подсказки честные: напишите тест на удаление и тест на -5.
Те же числа лежат в target/site/jacoco/jacoco.csv:
GROUP,PACKAGE,CLASS,INSTRUCTION_MISSED,INSTRUCTION_COVERED,BRANCH_MISSED,BRANCH_COVERED,LINE_MISSED,LINE_COVERED,...
blog,com.example.blog,InMemoryPostRepository,7,58,0,2,1,10,...
blog,com.example.blog,PostService,0,73,0,4,0,16,...
blog,com.example.shop,PriceCalculator,0,46,1,5,0,9,...Сколько достаточно
Покрытие показывает, что не протестировано, но ничего не говорит о качестве того, что протестировано. Тест без проверок выполняет все строки и даёт 100%, ничего не проверив. Относитесь к отчёту как к карте слепых зон, а не как к оценке. Многие команды ориентируются на 70–80% для бизнес-логики и не тестируют тривиальный код вроде геттеров ради цифры.
Частая ошибка
Если argLine в Surefire записан без @{argLine}, он затирает значение, которое подготовил JaCoCo. Тесты проходят, а отчёт молча пропадает:
<argLine>-javaagent:${org.mockito:mockito-core:jar} -Xshare:off</argLine>[INFO] --- jacoco:0.8.15:report (report) @ blog ---
[INFO] Skipping JaCoCo execution due to missing execution data file.Начинайте значение с @{argLine}: <argLine>@{argLine} -javaagent:...</argLine>. Surefire подставит туда агент JaCoCo во время запуска.