Files
memo/docs/orders/10-coverage-holes.md
T

4.8 KiB
Raw Blame History

Проект: /root/WORK/memo (Kotlin/JVM). Заказ на закрытие ТРЁХ дыр в покрытии, доказанных мутационной проверкой (python3 e2e/mutation_check.py --gradle ./gradlew). Мутация ломает боевой код, нужный тест обязан упасть. Сейчас три мутации выживают — тесты не проверяют то, ради чего написаны.

Правки — ТОЛЬКО в тестовых файлах. Боевой код (src/main) НЕ менять ни в одном модуле.

Дыра 1. memo-core/src/test/kotlin/memo/core/CollectionsTest.kt

Мутация it.isFile && it.extension == "md" -> it.name.endsWith("md") в Collections.kt ВЫЖИВАЕТ: в тесте все файлы — .md, поэтому подмена незаметна.

Дополнить тест findCollectionsReturnsOnlyDirsWithDirectMarkdown (имя и остальные проверки не менять):

  • добавить каталог File(root, "fakemd").mkdirs() — имя каталога заканчивается на "md", но .md-файлов внутри него нет; этот каталог НЕ должен попасть в результат (добавить проверку);
  • добавить файл File(root, "readme.txt").writeText("не markdown") — не должен ничего менять;
  • в конце теста добавить проверку: результат НЕ содержит File(root, "fakemd").absolutePath.

Дыра 2. memo-core/src/test/kotlin/memo/core/SearcherTest.kt

Мутация if (mode == SearchMode.LEX || mode == SearchMode.HYBRID) -> if (mode == SearchMode.LEX) ВЫЖИВАЕТ: в тесте hybridCombinesBoth «смысловой» чанк лексически содержит слова запроса («выпуск приложения»), поэтому его находит и чистый BM25, и вклад вектора ничем не доказан.

Дополнить тест hybridCombinesBoth:

  • заменить текст второго чанка на такой, у которого НЕТ общих токенов с запросом: запрос оставить "выпуск приложения 76.132" (то есть токены: выпуск, приложения, 76, 132), а чанк /sem.md сделать: "Конвейер поставки продуктов: компиляция, испытания, выкладка в кластер". Убедиться, что ни один токен запроса (кроме служебных длиной < 2) не встречается в этом тексте;
  • оставить проверку paths.contains("/exact.md") и paths.contains("/sem.md") — теперь вторая проверка выполнима ТОЛЬКО если векторный список участвует в слиянии. Имя теста и остальные тесты не менять.

Дыра 3. memo-watch/src/test/kotlin/memo/watch/WatcherTest.kt

Мутация _indexCalls.incrementAndGet() -> _indexCalls.get() в Watcher.kt ВЫЖИВАЕТ: тест modifyTriggersSingleIndexCall считает вызовы своим собственным AtomicInteger в лямбде index = {...} и встроенный счётчик watcher.indexCalls не проверяет вообще.

Дополнить тест modifyTriggersSingleIndexCall (имя и существующие проверки не менять):

  • в конце, рядом с assertEquals(1, counter.get(), ...), добавить: assertTrue(watcher.indexCalls >= 1, "встроенный счётчик indexCalls не растёт, получено ${watcher.indexCalls}").

Обязательная проверка (приложить вывод)

cd /root/WORK/memo python3 e2e/mutation_check.py --gradle ./gradlew

Ожидается строка ВСЕ МУТАЦИИ УБИТЫ в конце. Если какая-то мутация выжила — доработать тест, пока все 13 не будут убиты. Затем:

./gradlew test --rerun-tasks

— все тесты зелёные.

Коммит: git add -A && git commit -m "tests: закрыты три дыры в покрытии, найденные мутационным анализом"

СТРОГИЕ ЗАПРЕТЫ:

  • Не выводить план текстом; сразу правь файлы.
  • НЕ менять боевой код ни в memo-core, memo-cli, memo-mcp, memo-watch.
  • Не менять имена тестов, не удалять существующие проверки.
  • Не добавлять зависимости.