Files
enduro-trails/docs/work-items/ET-008/13-test-report.md
claude-bot af1a493cbf
Some checks failed
CI / lint (push) Failing after 4s
CI / test (push) Failing after 5s
CI / build (push) Has been skipped
CI / lint (pull_request) Failing after 4s
CI / test (pull_request) Failing after 5s
CI / build (pull_request) Has been skipped
test(ET-008): round 3 - all P0/P1 PASS, 141+22 tests green
2026-06-01 14:31:53 +00:00

210 lines
9.7 KiB
Markdown
Raw Permalink 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-008
title: "Test Report: GPS-треки с публичных платформ на карте"
version: 3
status: pass
created_at: 2026-06-01
updated_at: 2026-06-01
authors:
- "agent:tester"
tested_branch: feature/ET-008-gps
tested_commits:
- 1ffa178 "fix(gps-tracks): aggregate last_pipeline_run in health endpoint (REQ-F-12)"
- ba356ae "fix(gps-tracks): rename health fields and fix layer insert priority (F-04, F-05)"
- edbe9a3 "fix(gps-tracks): normalise GeoJSON props, add health fields, OSM meta fetch, z-order fix"
- 3734b98 "feat(ET-008): GPS tracks pipeline, API, frontend layer"
verdict: stage:ready-to-deploy
---
# Test Report — ET-008: GPS-треки с публичных платформ на карте (v3)
## Вердикт: **stage:ready-to-deploy**
Коммит `1ffa178` закрывает последний P1-дефект (F-04 — структура
`last_pipeline_run`). Все 141 pytest и 22 JS unit-теста зелёные. Все
P0/P1 находки из code-review v2 устранены. E2E и UI-тесты пропущены по
инфраструктурным причинам (бэкенд ET-008 не задеплоен на тест-стенд,
UI-раннер `/home/slin/tools/ui-test/run_tests.js` недоступен) — это не
дефект кода; рекомендуется выполнить E2E-прогон сразу после деплоя.
---
## Шаг 1 — Проверка окружения
| Endpoint | Статус | Детали |
|---|---|---|
| `GET /enduro/api/health` | ✅ 200 OK | `{"status":"ok","db_exists":true}` |
| `GET /enduro/api/gps-tracks/health` | ❌ 404 | ET-008 не задеплоен на стенд |
| `GET /enduro/api/gps-tracks?bbox=…` | ❌ 404 | ET-008 не задеплоен на стенд |
| `GET /enduro/api/gps-tracks/tiles/…mvt` | ❌ 404 | ET-008 не задеплоен на стенд |
| Фронтенд (HTML) | ✅ | `#public-tracks-cb`, `#sheet-gps-filters`, `gps_tracks.js` в разметке |
Бэкенд-роуты `/api/gps-tracks/*` возвращают 404 — статика ET-008
задеплоена, сервис не поднят. E2E и UI тесты выполнить невозможно до
деплоя.
---
## Шаг 2 — Функциональные тесты (`python -m pytest tests/ -v`)
```
cd /repos/enduro-trails/src/api
python -m pytest ../../tests/ -v --tb=short
```
**Результат: 141 passed, 0 failed, 7 warnings**
| Сюита | Тестов | Результат |
|---|---|---|
| `tests/api/test_gps_tracks_dedup.py` | 8 | ✅ PASS |
| `tests/api/test_gps_tracks_endpoint.py` | 15 | ✅ PASS |
| `tests/api/test_gps_tracks_mvt.py` | 9 | ✅ PASS |
| `tests/api/test_gps_tracks_sources_osm.py` | 21 | ✅ PASS |
| `tests/integration/test_routing_barriers.py` | 7 | ✅ PASS |
| `tests/unit/test_base_layer.py` | 22 | ✅ PASS |
| `tests/unit/test_gpx_upload.py` | 21 | ✅ PASS |
| `tests/unit/test_health.py` | 1 | ✅ PASS |
| `tests/unit/test_poi_toggle.py` | 10 | ✅ PASS |
| `tests/unit/test_unit_toggle.py` | 18 | ✅ PASS |
| `tests/web/test_gps_tracks.py` | 9 | ✅ PASS |
Предупреждения (7 шт.) — `DeprecationWarning` в `mapbox_vector_tile.encode`
(внешняя библиотека, некритично).
---
## Шаг 3 — E2E тесты (Playwright)
**SKIP** — бэкенд ET-008 не задеплоен на тест-стенд; Playwright-сценарии
E-01, E-02 (pipeline smoke) и E-10…E-12 (UI-фильтры) выполнить
невозможно. Рекомендуется запустить после `make deploy-test`.
---
## Шаг 4 — JS Unit-тесты (`node --test`)
```
node --test tests/web/gps_tracks.test.js
```
**Результат: 22 passed, 0 failed**
| Группа | Тестов | Результат |
|---|---|---|
| F-05: `_findGpsInsertPosition` — приоритет слоёв | 9 | ✅ PASS |
| Filters: начальное состояние `window.gpsTracksLayer` | 5 | ✅ PASS |
| Colors: палитра источников, активностей, fallback | 8 | ✅ PASS |
---
## Шаг 5 — UI / Visual тесты (TC-UI-01…TC-UI-20)
**SKIP**`/home/slin/tools/ui-test/run_tests.js` недоступен; бэкенд
ET-008 не отвечает на тест-стенде. Скриншоты TC-UI-01…TC-UI-20 не
сделаны.
---
## Верификация фиксов из `12-review.md`
### Итоговая таблица
| Finding | Severity | v2 | v3 | Вердикт |
|---|---|---|---|---|
| F-01: GeoJSON props несовместимы с MVT | P0 | PASS | PASS | ✅ PASS |
| F-02: `length_m` вместо `length_km` в GeoJSON | P1 | PASS | PASS | ✅ PASS |
| F-03: OSM batch-fetch и activity_type не реализованы | P1 | PASS | PASS | ✅ PASS |
| F-04: Health endpoint несовместим с REQ-F-12 | P1 | ⚠️ WARN | PASS | ✅ PASS |
| F-05: Z-order vs `gpx-layer-*` | P1 | PASS | PASS | ✅ PASS |
| `tests/web/gps_tracks.test.js` отсутствует | — | PASS | PASS | ✅ PASS |
| F-06: Нет валидации площади bbox | P2 | follow-up | follow-up | ⏭ follow-up |
| F-07: Дефолт sources включает disabled | P2 | follow-up | follow-up | ⏭ follow-up |
| F-08: LRU-кэш — на самом деле FIFO | P2 | follow-up | follow-up | ⏭ follow-up |
| F-09…F-12: P3-находки | P3 | follow-up | follow-up | ⏭ follow-up |
---
### F-04 [P1] → ✅ **PASS** (v2: ⚠️ WARN)
Коммит `1ffa178` реализует агрегацию строк `pipeline_runs` по
`MAX(started_at)` в полный контракт REQ-F-12:
```python
# endpoint.py, gps_health()
cur.execute("""
SELECT started_at, finished_at, region_id, source_id,
status, tracks_new, errors_json
FROM pipeline_runs
WHERE started_at = (SELECT MAX(started_at) FROM pipeline_runs)
ORDER BY region_id, source_id
""")
# → агрегация в:
{
"started_at": "...", "finished_at": "...",
"regions": ["tsfo_plus_chuvashia"],
"sources_ok": ["osm", "enduro_russia"],
"sources_error": [{"source": "ttrails", ...}],
"tracks_added": 100
}
```
Тест `test_i40_health_endpoint` (обновлён) проверяет:
- наличие всех 6 обязательных полей (`started_at`, `finished_at`,
`regions`, `sources_ok`, `sources_error`, `tracks_added`);
- типы (`list`, `int`);
- отсутствие сырых полей БД (`region_id`, `source_id`);
- конкретные агрегированные значения из фикстуры (2 региона,
2 ok-источника).
`test_i40_health_empty_db` подтверждает: при пустой БД — `last_pipeline_run: null`.
---
### Детали: что проверяют ключевые тесты ET-008
| Тест-ID | Связанный AC / REQ | Что проверяется |
|---|---|---|
| `test_f01_f02_geojson_normalised_properties` | AC-04, REQ-F-10 | GeoJSON `activity`, `source`, `length_km`, `activity_type` |
| `test_i20_filter_by_activity` | AC-04 | фильтр `?activity=enduro` возвращает только enduro |
| `test_i20_filter_by_source` | AC-04 | фильтр `?source=osm` возвращает только OSM |
| `test_i21_truncation` | AC-04 | `truncated=true`, `returned=500`, `total_in_bbox=1500` |
| `test_i22_invalid_bbox_returns_400` (7 param) | AC-04 | 400 на невалидные bbox |
| `test_i30_mvt_tile_returns` | AC-05 | `200 application/x-protobuf`, layer `gps_tracks` |
| `test_i31_cache_hit` | AC-05, REQ-NF-04 | `X-Cache: HIT` на повторный запрос |
| `test_i40_health_endpoint` | AC-06, REQ-F-12 | все поля health, агрегированный `last_pipeline_run` |
| `test_u13_merge_sources_on_upsert` | AC-03, REQ-F-08 | дедупликация: union sources |
| `test_u44_xxe_protection` | REQ-NF-01 | defusedxml блокирует XXE |
| `test_u45_meta_response_with_known_tag` | REQ-F-04, REQ-F-07 | OSM tag → `activity_type` |
| `test_gps_tracks_find_insert_position_priority_gpx_first` | AC-10, §7.1 | gpx-layer-* > route-* |
---
## Открытые P2/P3 — follow-up (не меняют вердикт)
| Finding | Severity | Описание | Рекомендация |
|---|---|---|---|
| F-06 | P2 | Нет проверки площади bbox | Добавить max area ≤ 100°² в `_parse_bbox()` |
| F-07 | P2 | Дефолт sources содержит disabled-источники | Инициализировать из `/api/gps-tracks/health.tracks_by_source` |
| F-08 | P2 | LRU-кэш — на самом деле FIFO | `OrderedDict` с `move_to_end` при чтении |
| F-09 | P3 | `save_user_field` в YAML не читается кодом | Обработать в upsert |
| F-10 | P3 | Лишний `import pytest_asyncio` | Убрать |
| F-11 | P3 | `MockRow(dict)` вместо `sqlite3.Row` | Рефактор тестов |
| F-12 | P3 | Лишняя проверка `"source_priority" in existing.keys()` | Упростить |
---
## Рекомендации для деплоя
После выполнения `make deploy-test` или `docker compose up -d` на тест-стенде
с веткой `feature/ET-008-gps`:
1. **Smoke API:**
```bash
curl https://openclaw.mva154.duckdns.org/enduro/api/gps-tracks/health
curl "https://openclaw.mva154.duckdns.org/enduro/api/gps-tracks?bbox=37.0,55.0,38.0,56.0&limit=5"
```
2. **E2E Playwright:** E-01 (pipeline smoke), E-02 (dedup), E-10…E-12 (filters).
3. **UI тесты:** TC-UI-01…TC-UI-20 через `run_tests.js` (при наличии раннера).
4. **P2 follow-up** можно закрыть отдельным PR после приёмки основного.