Files
autotest/polygon-docs/sonnet-compare-testing-prompt.md
T

185 lines
9.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Соннет: анализ сравнительного тестирования Polygon ↔ реальный Nubes API
> Адресат: Claude Sonnet 4.6 (новый чат)
> ⛔ Режим: **диалог**. Задавай встречные вопросы если нужно уточнение.
> ⛔ НЕ редактировать файлы. Только анализ и советы в чат.
---
## Контекст
**Polygon** (v0.5.4) — эмулятор REST API облачной платформы Nubes.
3 стенда: dev (37 сервисов), test (37), prod (35). YAML-конфиги генерируются
из терраформ-репы (`~/tf_provider/generated/{dev,test,prod}/resources_yaml/`).
**Реальное API**:
- `https://lk-api-gateway-dev.ngcloud.ru/api/v1/svc`
- `https://lk-api-gateway-test.ngcloud.ru/api/v1/svc`
- `https://lk-api-gateway.ngcloud.ru/api/v1/svc`
Токены в `secrets/{dev,test,prod}.token`.
## Что сделано
Написан скрипт `compare_test.py` который сравнивает read-only эндпоинты
полигона и реального API:
- `GET /services` — список сервисов
- `GET /services/{id}` — операции (svcOperationId, operation, kind, action)
- `GET /instanceOperations/default/{id}` — cfsParams (id, код, dataType, isRequired)
Первый прогон показал:
- **dev**: операции совпадают, но у 2 параметров `dataType: None` вместо `"string"`
- **test**: аналогично
- **prod**: чисто, расхождений нет
Также обнаружено что реальный API возвращает HTML-entities в dataType
(`integer >= 0`), а полигон — чистый текст (`integer >= 0`).
Полигон здесь правильнее реального API.
## Ключевой нюанс: идеология стендов
Стенды НЕ идентичны. **Dev опережает test, test опережает prod**.
Новые сервисы и параметры появляются сначала в dev, потом через какое-то
время попадают в test, и только затем в prod. Поэтому:
- Если в dev-полигоне и dev-реальном API есть расхождения — это может быть
нормально (реальный API уже обновился, а YAML в полигоне — ещё нет)
- Если в prod есть расхождения — скорее всего баг в генерации YAML
- Нужно различать «допустимое отставание» и «реальный баг»
## Что нужно от тебя
### 1. Стратегия сравнительного тестирования
Как правильно сравнивать полигон с реальным API учитывая что:
- Стенды могут и должны отличаться
- YAML генерируется не в реальном времени, а батчами из терраформа
- Некоторые сервисы есть в реальном API но НЕ в терраформе (их не тестируем)
Что должно считаться PASS, а что FAIL? Какие допуски?
### 2. Какие ещё эндпоинты сравнивать?
Сейчас сравниваются 3 read-only эндпоинта. Какие ещё можно безопасно
сравнять? Что ещё есть в реальном API такого что полигон должен
повторять один-в-один?
### 3. Периодичность и автоматизация
Как часто запускать сравнение? При каких событиях (изменение терраформа,
деплой полигона)? Должно ли это быть частью CI?
### 4. dataType: None
В `from_stands.py` для некоторых параметров dataType падает в None
(хотя дефолт "string"). Где конкретно искать причину?
### 5. Общие советы
Что ещё мы упускаем в тестировании полигона? Какие сценарии, краевые
случаи, проверки контрактов?
---
## Формат диалога
Ты можешь:
- Сразу дать развёрнутый ответ по всем пунктам
- Или задать уточняющие вопросы — и тогда я отвечу, а ты продолжишь
Я хочу чтобы в итоге получился **конкретный план действий**:
что тестировать, как часто, что считать ошибкой, что — допустимым
расхождением.
---
## Ответ Соннета (2026-08-02)
### 4. dataType: None — первопричина найдена
`dict.get(key, default)` возвращает `default` **только если ключ отсутствует**.
Если в YAML написано `data_type: null` — ключ *есть*, значение — `None`,
дефолт `"string"` не срабатывает.
### Мои ответы
**Q4.1 — data_type: null в YAML?** Проверил — в терраформ-YAML нет
`data_type: null`. Реальный API возвращает `dataType: null` для параметра
`nestedRefExample` (param 396). Полигон возвращает `"string"` — он ПРАВИЛЬНО
применяет дефолт там, где реальный API отдаёт null. Это не баг полигона,
а улучшение.
**Q4.2 — _convert_sub_params?** Та же уязвимость потенциально есть, но не
проявляется — sub_params всегда имеют data_type.
**Q1.1 — частота регенерации YAML?** ВРУЧНУЮ. `from_stands.py` запускается
человеком когда он вспомнит. Никакого cron/webhook.
**Q1.2 — лаг от реального API до YAML?** Непредсказуемо. От часов до недель.
Зависит от того когда кто-то запустит `from_stands.py`.
**Q1.3 — потребитель результатов?** Разработчик. Ему нужно знать «полигон
устарел, перегенери YAML», а не «полигон сломан».
**Q2.1 — дополнительные эндпоинты в реальном API?** Не проверял. Надо
сравнить полный список эндпоинтов.
**Q2.2 — lifecycle поля?** Не сравниваются в текущем compare_test.py. Надо
добавить.
---
## Ответ Соннета — раунд 2
### Три категории расхождений — 👍 принимаю
| Категория | Значение | Реакция |
|---|---|---|
| 🔴 REAL BUG | полигон ≠ реальный API, полигон неправ | FAIL |
| 🟡 LAG | новый параметр в реальном API, нет в полигоне | WARN |
| 🟢 POLYGON BETTER | реальный API отдаёт null/entities, полигон — правильно | INFO |
Для prod 🟡 LAG тоже должен быть заметен.
### Мои ответы — раунд 2
**Q5.1 — сервис есть в полигоне, пропал из реального API?**
Теоретически да — если сервис удалили из реального API, а terraform ещё
не обновили. Это 🔴 REAL BUG и должно быть FAIL. Полигон не должен
эмулировать несуществующие сервисы.
**Q5.2 — HTML-entities?**
Нормализовать при сравнении: `html.unescape()` для real API перед сравнением.
Считать 🟢 POLYGON BETTER, не ошибка.
**Q5.3 — lifecycle поля?**
Проверил — ни реальный API, ни полигон НЕ возвращают `lifecycle` в
`GET /services/{id}`. Сравнивать нечего, вопрос снят.
---
## Ответ Соннета — раунд 3 (финальный)
### Q6.1 — defaultValue, valueList и др.
Реальный API возвращает **29 полей** на каждый cfsParam: `defaultValue`,
`valueList`, `isModifiable`, `isRequired`, `isHidden`, `descr`, `man`,
`regex`, `maxlength`, `minvalue` и т.д. Полигон возвращает подмножество
из ~6-8 полей.
Сравнивать нужно только те поля, которые `from_stands.py` реально генерирует:
`defaultValue`, `valueList`, `isModifiable`, `isRequired`. Остальные либо
отсутствуют в терраформ-YAML, либо не имеют смысла для мока.
### Q6.2 — cfsParamsByOp
Это **внутренний индекс** полигона, не API-эндпоинт. Связь «какие параметры
к какой операции» уже проверяется через `GET /instanceOperations/default/{id}`
— если в ответе правильный набор параметров, значит cfsParamsByOp правильный.
Отдельно сравнивать не нужно.
### Q6.3 — формат вывода
stdout + exit code — достаточно. Разработчик запускает вручную, смотрит
глазами. Файл отчёта переусложнит. Если понадобится история — можно потом.