From 769b4d3dbd8da45692fbdb33ffd7029cc6a1632a Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Sat, 25 Jul 2026 15:35:02 +0300 Subject: [PATCH] =?UTF-8?q?docs(tests):=20=D0=BE=D0=BF=D0=B8=D1=81=D0=B0?= =?UTF-8?q?=D1=82=D1=8C=20=D0=B2=D1=81=D0=B5=20=D0=BF=D0=BE=D0=BB=D1=8F=20?= =?UTF-8?q?=D1=82=D0=B5=D1=81=D1=82-=D0=BA=D0=B5=D0=B9=D1=81=D0=B0=20?= =?UTF-8?q?=D0=B2=20README?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Таблица «Все поля кейса» отставала от раннера: не были описаны idempotent, runtimeOnly, skipValidation, а expect ограничивался упоминанием files/ stdoutContains/stdoutNotContains — preserves и структура preRun не документировались вовсе. Из-за таких пробелов формат кейса приходится выяснять по коду — а это ровно тот способ, который однажды дал 9 кейсов meta-edit с несуществующим ключом: тесты зелёные, навык no-op, снэпшот фиксирует исходник. Добавлено (сверено с runner.mjs и с реальными кейсами): - idempotent, runtimeOnly, skipValidation в основную таблицу; - таблица ключей expect + вложенная таблица preserves (file/bom/eol/encoding/ finalNewline/noCR13) с пометкой, что preserves и эталон дополняют друг друга: первый следит за байтовым стилем, второй за структурой; - формы шагов preRun (прогон навыка и writeFile). editFile намеренно не описан — это шаг интеграционных тестов, не preRun кейса. Co-Authored-By: Claude Opus 5 (1M context) --- tests/skills/README.md | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/tests/skills/README.md b/tests/skills/README.md index 18738abd..cf5f7be4 100644 --- a/tests/skills/README.md +++ b/tests/skills/README.md @@ -227,10 +227,45 @@ ibcmd-проход автоматически `○ skipped`, если рядом | `setup` | нет | Переопределение setup из `_skill.json` | | `outputPath` | нет | Относительный путь для навыков с `-OutputPath` | | `args_extra` | нет | Массив дополнительных CLI-аргументов | -| `preRun` | нет | Массив шагов подготовки (создание объектов и т.п.) | -| `expect` | нет | Дополнительные проверки: `files`, `stdoutContains` (строка/массив), `stdoutNotContains` (строка/массив) | +| `preRun` | нет | Массив шагов подготовки (см. ниже) | +| `expect` | нет | Дополнительные проверки (см. ниже) | | `expectError` | нет | `true` или строка — ожидается ошибка | | `noSnapshot` | нет | Непустая строка с причиной — кейс объявляет, что эталон не нужен (см. «Эталоны») | +| `idempotent` | нет | `true` — повторный прогон с теми же аргументами должен дать байт-в-байт тот же `workDir` | +| `runtimeOnly` | нет | `"powershell"` / `"python"` — кейс имеет смысл только на одном порте, на другом `○ skipped` | +| `skipValidation` | нет | `true` — не запускать `postValidate` из `_skill.json` (только при `--with-validation`) | + +### Ключи `expect` + +| Ключ | Описание | +|---|---| +| `files` | Массив путей относительно `workDir` — каждый должен существовать после прогона | +| `stdoutContains` | Строка или массив строк — все должны присутствовать в stdout | +| `stdoutNotContains` | Строка или массив строк — ни одной не должно быть в stdout | +| `preserves` | Объект (или массив объектов) — байтовые свойства файла, которые навык обязан сохранить | + +`preserves` проверяет то, что снэпшот-сравнение нормализует и потому увидеть не может: + +| Ключ | Описание | +|---|---| +| `file` | Путь к файлу относительно `workDir` (обязателен) | +| `bom` | `true`/`false` — наличие UTF-8 BOM | +| `eol` | `"crlf"` / `"lf"` | +| `encoding` | Ожидаемое значение в XML-декларации, напр. `"UTF-8"` | +| `finalNewline` | `true`/`false` — перевод строки в конце файла | +| `noCR13` | `true` — в выходе не должно быть литерала ` ` | + +`preserves` и эталон **дополняют** друг друга: первый следит за байтовым стилем файла, второй — за +структурой содержимого. Наличие одного не отменяет необходимости другого. + +### Шаги `preRun` + +Массив шагов, выполняемых до запуска проверяемого навыка: + +| Форма шага | Описание | +|---|---| +| `{ "script": "<навык>/scripts/<файл>", "input": {...}, "args": { "-Flag": "{inputFile}" } }` | Прогон другого навыка для подготовки фикстуры. Плейсхолдеры: `{inputFile}`, `{workDir}` | +| `{ "writeFile": { "path": "<путь>", "content": "<строка или объект>" } }` | Записать произвольный файл в `workDir` (объект сериализуется в JSON) | ## Эталоны (snapshots)