Files
enduro-trails/docs/work-items/ET-015/13-test-report.md
claude-bot c05a834c26
All checks were successful
CI / lint (push) Successful in 4s
CI / lint (pull_request) Successful in 5s
CI / test (push) Successful in 13s
CI / build (push) Successful in 2s
CI / test (pull_request) Successful in 12s
CI / build (pull_request) Successful in 1s
tester(ET): auto-commit from tester run_id=105
2026-06-05 15:39:54 +00:00

206 lines
9.6 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.
---
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».