334015a2bd
Build LLM Proxy / Build and push (release) Successful in 44s
- transformThinkMessage/transformThinkChunk/streamSseWithThinkTags сделаны internal ради тестируемости (логика не менялась) - +24 теста: ThinkTagTransformTest (9), ThinkTagChunkTest (8), ThinkTagStreamTest (7) - ConfigLogicTest: ассерт приоритета источников был неразличающим (провайдер и апстрим давали одинаковый результат) — заменён на различающиеся значения - kotlinx-coroutines-test для тестов каналов ktor - Gitea Actions: шаг Run tests (jvmTest) — раньше CI тесты не гонял вовсе - TESTING.md: что покрыто + мутационная приёмка
46 lines
3.8 KiB
Markdown
46 lines
3.8 KiB
Markdown
# Тестирование llm-proxy
|
|
|
|
Все тесты — обычные модульные, живут в `src/commonTest/kotlin/pw/binom/llmproxy/`.
|
|
|
|
## Запуск
|
|
|
|
- `./gradlew jvmTest` — прогнать все тесты;
|
|
- `./gradlew clean jvmTest fatJar` — полная сборка с нуля;
|
|
- результат смотреть в `build/test-results/jvmTest/*.xml` (атрибуты `tests`/`failures`/`errors`), потому что строки вида «N tests completed» печатаются только при падениях.
|
|
|
|
## Что покрыто
|
|
|
|
| Файл | Что проверяет |
|
|
| --- | --- |
|
|
| `ThinkTagSplitterTest` | Автомат рассечения think-тегов: passthrough при off, вырезание рассуждений при split, отбрасывание при strip, удержание разрезанного тега, несколько блоков, незакрытый блок; |
|
|
| `ConfigLogicTest` | Разбор конфига, приоритет источников (апстрим важнее провайдера), слияние патчей, выбор апстрима и лимиты конкурентности, заголовки, сессии; |
|
|
| `ThinkTagTransformTest` | Non-stream путь `transformThinkMessage`: перенос рассуждений в `reasoning_content`, дописывание к уже имеющемуся, strip, незакрытый блок, отсутствие изменений → null; |
|
|
| `ThinkTagChunkTest` | SSE-чанки `transformThinkChunk`: удержание хвоста тега между чанками, независимые сплиттеры по index, удаление пустого `content`; |
|
|
| `ThinkTagStreamTest` | Обвязка стрима `streamSseWithThinkTags`: разрез тега между data-событиями, сброс удержанного хвоста в финиш-чанке, прохождение служебных строк и `[DONE]`, битый JSON, чанк без choices, strip. |
|
|
|
|
## Проверка качества тестов (мутационная приёмка)
|
|
|
|
Приём по шагам:
|
|
|
|
1. Забэкапить файл.
|
|
2. Внести РОВНО одну поломку в боевой код.
|
|
3. Прогнать `./gradlew cleanJvmTest jvmTest`.
|
|
4. Посмотреть XML — тест, который не упал, считается пустым.
|
|
5. Откатить (`git checkout -- <файл>`).
|
|
|
|
Обязательно: `cleanJvmTest` обязателен, иначе прогон не перезапустится.
|
|
|
|
Проверенные мутации, каждая из которых ДОЛЖНА ронять тесты:
|
|
|
|
- `transformThinkMessage` возвращает null → падают тесты non-stream;
|
|
- `transformThinkChunk` возвращает null → падают тесты чанков и стрима;
|
|
- блок финиш-чанка в `streamSseWithThinkTags` не выполняется → падает тест про удержанный хвост;
|
|
- `holdableSuffix` всегда 0 (хвост тега не удерживается) → падают тесты автомата, чанков и стрима;
|
|
- `strip` начинает отдавать рассуждения → падает тест автомата.
|
|
|
|
Правило: боевой код нельзя подгонять под тест; если тест не проходит, неверен тест.
|
|
|
|
## Известное ограничение
|
|
|
|
Живой стрим в реальном апстриме модульными тестами не проверяется: обвязка испытывается на синтетическом SSE через каналы ktor. Реальный апстрим проверяется только после деплоя.
|