206 lines
9.6 KiB
Markdown
206 lines
9.6 KiB
Markdown
---
|
||
type: test-report
|
||
work_item_id: ET-015
|
||
verdict: READY_TO_DEPLOY
|
||
version: 1
|
||
---
|
||
|
||
# Test Report ET-015 — Healthcheck enduro-trails-app
|
||
|
||
**Branch:** `feature/ET-015-healthcheck-enduro-trails-app-`
|
||
**Base:** `main`
|
||
**Tester:** agent:tester
|
||
**Date:** 2026-06-05
|
||
**Test plan:** [04-test-plan.yaml](04-test-plan.yaml)
|
||
**Acceptance criteria:** [03-acceptance-criteria.md](03-acceptance-criteria.md)
|
||
|
||
## TL;DR
|
||
|
||
**16/16** ST + UT тестов пройдено. E2E-02 (`/api/health` снаружи на mva154)
|
||
возвращает `HTTP 200` за **0.111 s**. Эндпоинт `src/api/main.py::health()` не
|
||
изменён. Интеграционные IT-01..IT-04 и E2E-01 закрываются на этапе деплоя
|
||
(требуют live docker compose / ssh mva154) — это явно заложено в
|
||
`04-test-plan.yaml::done_when`.
|
||
|
||
**Вердикт: READY_TO_DEPLOY.**
|
||
|
||
## Окружение
|
||
|
||
| Параметр | Значение |
|
||
|----------|----------|
|
||
| Python | 3.12.13 |
|
||
| pytest | 8.3.3 |
|
||
| Repo HEAD | `d501bcb` (reviewer auto-commit) |
|
||
| Доступ к mva154 | через HTTPS (curl недоступен → проверка через python urllib) |
|
||
| Docker в окружении tester | **недоступен** (`docker: command not found`) |
|
||
|
||
Pre-flight: `GET https://openclaw.mva154.duckdns.org/enduro/api/health` →
|
||
`HTTP 200`, body `{"status":"ok","db_path":"/app/data/centralfederal.sqlite","db_exists":true}`,
|
||
time `0.111 s`. Тестовая среда жива.
|
||
|
||
## Результаты
|
||
|
||
### Static (ST-*) и Unit (UT-*)
|
||
|
||
Запуск:
|
||
|
||
```
|
||
python3 -m pytest tests/static/test_healthcheck_compose.py \
|
||
tests/unit/test_healthcheck_oneliner.py -v
|
||
```
|
||
|
||
Итог: **16 passed in 2.92s**.
|
||
|
||
| ID | Имя | AC | Результат |
|
||
|----|-----|----|-----------|
|
||
| ST-01 | `test_st01_healthcheck_does_not_use_curl` | AC-03 | PASS |
|
||
| ST-02 | `test_st02_dockerfile_does_not_apt_install_curl_or_wget` | AC-04 | PASS |
|
||
| ST-03 | `test_st03_healthcheck_uses_python_and_stdlib` | AC-06 | PASS |
|
||
| ST-04 | `test_st04_internal_timeout_less_than_external` (3 < 5) | AC-07 | PASS |
|
||
| ST-05 | `git diff main..HEAD -- src/api/main.py` (empty) | AC-08 | PASS |
|
||
| ST-06 | `test_st06_changelog_mentions_et015` | AC-09 | PASS |
|
||
| ST-07 | `test_st07_adr_exists` (ADR-020) | AC-10 | PASS |
|
||
| ST-reg | `test_app_healthcheck_target_is_local_api_health` | regression | PASS |
|
||
| ST-reg | `test_app_healthcheck_has_start_period` (20s) | regression | PASS |
|
||
| ST-reg | `test_app_healthcheck_preserves_baseline_params[interval-30]` | regression | PASS |
|
||
| ST-reg | `test_app_healthcheck_preserves_baseline_params[retries-3]` | regression | PASS |
|
||
| UT-01 | `test_ut01_returns_zero_on_http_200` | AC-06 | PASS |
|
||
| UT-02 | `test_ut02_returns_nonzero_when_port_unused` | AC-05, AC-06 | PASS |
|
||
| UT-03 | `test_ut03_returns_nonzero_on_non_2xx[301]` | AC-06 | PASS |
|
||
| UT-03 | `test_ut03_returns_nonzero_on_non_2xx[404]` | AC-06 | PASS |
|
||
| UT-03 | `test_ut03_returns_nonzero_on_non_2xx[500]` | AC-06 | PASS |
|
||
| UT-03 | `test_ut03_returns_nonzero_on_non_2xx[503]` | AC-06 | PASS |
|
||
|
||
Важная техническая деталь: unit-тесты one-liner'а **читают исходную
|
||
команду из `docker-compose.yml`** (а не дублируют её) — если в будущем
|
||
кто-то изменит one-liner в compose и сломает контракт exit-кода, UT-01/02/03
|
||
немедленно покраснеют.
|
||
|
||
### Integration (IT-*) — на стороне deployer
|
||
|
||
IT-01..IT-04 требуют локального `docker compose` и доступа к
|
||
`/home/slin/enduro-trails/data` — в среде tester'а Docker недоступен
|
||
(`docker: command not found`). Согласно `04-test-plan.yaml`
|
||
эти тесты автоматизируемые, но физически выполняются:
|
||
|
||
- IT-01 (healthy за ≤ 120s) — закрывается deployer'ом сразу после
|
||
`make deploy-test` на mva154.
|
||
- IT-02 (стабилен 5 минут) — закрывается мониторингом после деплоя.
|
||
- IT-03 (переход в unhealthy при остановке uvicorn) — рекомендуется
|
||
отдельным smoke-шагом в post-deploy чек-листе; **не блокирует deploy**,
|
||
т.к. unit UT-02 уже доказал, что one-liner возвращает ненулевой exit-code
|
||
при недоступном порту.
|
||
- IT-04 (не требует ребилда) — статически подтверждается тем, что
|
||
`git diff main..HEAD -- Dockerfile` пуст, образ не меняется
|
||
(что также проверяет ST-02).
|
||
|
||
**Передача:** IT-01/IT-02/IT-03 → deployer (см. ниже секцию «Pending»).
|
||
|
||
### E2E
|
||
|
||
| ID | Имя | Результат |
|
||
|----|-----|-----------|
|
||
| E2E-01 | После `make deploy-test` контейнер healthy на mva154 (3 замера) | **Pending** — закрывается deployer'ом |
|
||
| E2E-02 | Приложение продолжает отвечать снаружи | **PASS** — `HTTP 200`, `0.111 s` (см. pre-flight) |
|
||
|
||
### Полный pytest-набор репозитория
|
||
|
||
`python3 -m pytest tests/` не собирается из-за пред-существующих
|
||
проблем окружения: отсутствуют `shapely`, `defusedxml`,
|
||
`mapbox_vector_tile` (15 collection errors). Это **не связано с ET-015**
|
||
(изменение чисто инфраструктурное — `docker-compose.yml`, CHANGELOG,
|
||
docs/tests; `src/api/` не трогается). Зафиксировано как наблюдение,
|
||
не блокирующее этот work item.
|
||
|
||
## Visual / UI тесты
|
||
|
||
Файл `docs/work-items/ET-015/04b-ui-test-cases.md` **отсутствует**
|
||
(инфраструктурная задача, UI не задействован). Шаг 4 теста-плана
|
||
пропущен согласно инструкции tester'а.
|
||
|
||
## Покрытие Acceptance Criteria
|
||
|
||
| AC | Тесты | Статус |
|
||
|----|-------|--------|
|
||
| AC-01 | IT-01, E2E-01 | Pending (deployer) |
|
||
| AC-02 | IT-02, E2E-01 | Pending (deployer) |
|
||
| AC-03 | ST-01 | **PASS** |
|
||
| AC-04 | ST-02, IT-04 | **PASS (static)** |
|
||
| AC-05 | UT-02, IT-03 | **PASS (unit)** + Pending (IT-03 на deployer) |
|
||
| AC-06 | ST-03, UT-01, UT-03 (4 кейса) | **PASS** |
|
||
| AC-07 | ST-04 (3 < 5) | **PASS** |
|
||
| AC-08 | ST-05, E2E-02 | **PASS** |
|
||
| AC-09 | ST-06 | **PASS** |
|
||
| AC-10 | ST-07 | **PASS** |
|
||
|
||
## Findings
|
||
|
||
### P0 (blocker)
|
||
Нет.
|
||
|
||
### P1 (must-fix)
|
||
Нет.
|
||
|
||
### P2 (should-fix)
|
||
Нет.
|
||
|
||
### P3 (nice-to-have)
|
||
|
||
- **P3-T1.** Pre-существующие сбои окружения при сборе общего
|
||
pytest-набора (`shapely`, `defusedxml`, `mapbox_vector_tile`
|
||
отсутствуют). Не относится к ET-015, но мешает запускать общий
|
||
smoke за один проход. Рекомендуется отдельной задачей привести
|
||
test-окружение в порядок (CI-образ или `requirements-test.txt`).
|
||
- **P3-T2.** В среде tester'а отсутствует `curl` — пришлось делать
|
||
E2E-02 через `python -m urllib.request`. Результат идентичен
|
||
(HTTP 200, ~111 ms), но в чек-листе деплоя стоит оставить
|
||
команду `curl -sS` именно как написана в плане.
|
||
|
||
(Все три P3 из review (`12-review.md`) перенесены как известные
|
||
вопросы документации/стиля, не блокирующие.)
|
||
|
||
## Pending (передаётся deployer'у)
|
||
|
||
Эти проверки **обязательны** до закрытия задачи, но физически
|
||
выполняются на mva154 после `make deploy-test`:
|
||
|
||
1. **IT-01 / E2E-01 — healthy за ≤ 120 s после деплоя.**
|
||
```
|
||
ssh mva154 'docker inspect enduro-trails-app-1 \
|
||
--format "{{.State.Health.Status}} (streak {{.State.Health.FailingStreak}})"'
|
||
# ожидается: healthy (streak 0)
|
||
```
|
||
2. **IT-02 / E2E-01 — стабилен через 5 и 10 минут.**
|
||
Повторить команду выше через 5 и 10 минут после деплоя.
|
||
3. **IT-03 — переход в unhealthy при отказе.** *(опционально, smoke)*
|
||
```
|
||
ssh mva154 'docker exec enduro-trails-app-1 sh -c "pkill -STOP -f uvicorn"'
|
||
# подождать ≤ 120s
|
||
ssh mva154 'docker inspect enduro-trails-app-1 --format "{{.State.Health.Status}}"'
|
||
# ожидается: unhealthy
|
||
ssh mva154 'docker compose restart app' # вернуть в строй
|
||
```
|
||
|
||
## Команды воспроизведения
|
||
|
||
```bash
|
||
# ST + UT
|
||
python3 -m pytest tests/static/test_healthcheck_compose.py \
|
||
tests/unit/test_healthcheck_oneliner.py -v
|
||
# E2E-02
|
||
python3 -c "import urllib.request,time; t=time.time(); \
|
||
r=urllib.request.urlopen('https://openclaw.mva154.duckdns.org/enduro/api/health', timeout=10); \
|
||
print(r.status, f'{time.time()-t:.3f}s', r.read().decode())"
|
||
```
|
||
|
||
## Вердикт
|
||
|
||
**READY_TO_DEPLOY (stage:ready-to-deploy).**
|
||
|
||
Все автоматизируемые статические и unit-проверки пройдены (16/16).
|
||
Эндпоинт `/api/health` на test-среде жив, отдаёт 200 за ~111 ms.
|
||
`src/api/main.py` и `Dockerfile` не изменены — поведение приложения
|
||
гарантированно сохранено. P0/P1/P2 пусты. Передаю deployer'у;
|
||
финальные AC-01/AC-02 закрываются после `make deploy-test` по чек-листу
|
||
в секции «Pending».
|