Skip to content

[BE] Pitest using - investigation about it to our project #2962

Description

@ElenaSpb

Pitest

Pitest — это самый серьёзный инструмент из «пирамиды»: он объективно отвечает на вопрос «а тесты вообще кусаются, или просто зелёные». Расскажу по делу, включая честные Kotlin-подводные камни (это ключевое
для вашего стека).

  1. Идея: мутационное тестирование

Обычное покрытие (jacoco) считает «какие строки исполнились». Pitest считает другое — «какие поломки кода тесты ловят».

Механика:

  1. Pitest берёт твой байткод и вносит маленькую поломку — мутацию. Например >= → >, + → -, return x → return null, убирает вызов метода, инвертирует if.
  2. Прогоняет тесты против этого «мутанта».
  3. Итог по каждому мутанту:
    - KILLED — хотя бы один тест упал. 👍 тесты поймали поломку.
    - SURVIVED — все тесты зелёные, хотя код сломан. 👎 дыра в ассертах — ровно твой «зелёный, но слабый».
    - NO_COVERAGE — мутанта даже не исполнил ни один тест (пробел покрытия).
    - TIMED_OUT / NON_VIABLE — мутация зациклила/не скомпилировалась (шум).

Mutation score = KILLED / всего мутантов. Это метрика силы тестов, а не факта исполнения.

  1. Почему это бьёт точнее jacoco

Классический пример на вашем коде — isDoneWell:

repetitionIndex >= minRepetitionIndex && rightAnswersIndex >= minRightAnswersIndex

  • jacoco: если хоть один тест сюда зашёл — строка «покрыта», 100%.
  • Pitest: сгенерит мутантов >=→>, &&→||, >=→<… Если у тебя нет теста ровно на граничное значение == 0.8 или на «один индекс прошёл, другой нет» — эти мутанты SURVIVED. Ты сразу видишь: пороговая логика тестами не
    зафиксирована, хотя покрытие «зелёное 100%».

Как бы встроилось в наш Gradle Kotlin DSL

Плагин info.solidsoft.pitest (gradle-pitest-plugin), с JUnit5-мостом:

plugins {
id("info.solidsoft.pitest") version "1.15.0" // проверить актуальную
}

dependencies {
// мост для JUnit 5 (у вас JUnit Platform)
pitest("org.pitest:pitest-junit5-plugin:1.2.1")
}

pitest {
junit5PluginVersion.set("1.2.1")
// не весь проект! только ценное ядро:
targetClasses.set(listOf("com.epam.brn.service."))
targetTests.set(listOf("com.epam.brn.service.
"))
threads.set(Runtime.getRuntime().availableProcessors())
outputFormats.set(listOf("HTML", "XML"))
timestampedReports.set(false)
// на старте не заваливать build — без порога:
// mutationThreshold.set(60)
}

Запуск: gradlew pitest → HTML-отчёт в build/reports/pitest/ с построчной подсветкой survived-мутантов.

Activity

  1. self-assigned this
    on Sep 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions