test: README для tests/ + фикс теста test_boolean (BOOLEAN NOT NULL); 102 passed
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
# Тесты contracts-flask
|
||||
|
||||
Набор pytest-тестов под актуальный код сервиса (`site/`).
|
||||
Покрытие: юнит (чистая логика), интеграционные (SQLite), HTTP-эндпоинты (Flask test client), безопасность.
|
||||
|
||||
## Запуск
|
||||
|
||||
```bash
|
||||
cd contracts-flask
|
||||
pytest tests/ -q
|
||||
```
|
||||
|
||||
pytest установлен в venv: `/home/naeel/nubes/contracts/.venv/bin/python -m pytest tests/ -q`.
|
||||
|
||||
## Файлы
|
||||
|
||||
| Файл | Что тестирует |
|
||||
|---|---|
|
||||
| `conftest.py` | site/ в `sys.path`; фикстура `db` — изолированная БД (временный `DB_PATH` + свежая схема); защита реальной `/tmp/contracts.db` от пересоздания |
|
||||
| `test_metrics.py` | `services/metrics.py`: `normalize_date`, `check_arithmetic` (sum == price×qty), `_to_decimal`, `ClassifyMetrics` |
|
||||
| `test_grouping.py` | `services/grouping.py`: `normalize_number`, `group_documents` (группировка contract+supplement, unresolved), `apply_groups` (mock db) |
|
||||
| `test_llm_client.py` | `services/llm_client.py`: `FakeLLMClient` (точное/частичное совпадение, default, история вызовов), `HttpxLLMClient` |
|
||||
| `test_llm.py` | `services/llm.py`: `call_llm` — парсинг plain JSON и markdown-обёрток (```json) |
|
||||
| `test_classify.py` | `services/classify.py`: garbage-фильтры по имени/заголовку, `_safe_json_parse` (7 edge-case: trailing comma, chatter, пусто), `_smart_extract` |
|
||||
| `test_parse.py` | `services/parse.py`: `parse_file` (text/docx/pdf, ошибки), `_parse_text` |
|
||||
| `test_connection.py` | `db/connection.py`: `_pg_to_sqlite` (все замены %s/::jsonb/BOOLEAN/ILIKE/TRUE), `_extract_table` |
|
||||
| `test_spec_events.py` | `db/spec_events.py`: `apply_ops` (ADD/UPDATE/DELETE/UNRESOLVED/unknown), `clear_current`, `reset`, `_hash`, `get_next_seq` |
|
||||
| `test_spec_current.py` | `db/spec_current.py`: `list_by_contract` (порядок), `get_elements_json` |
|
||||
| `test_process_pipeline.py` | `services/process.py`: `run_pipeline` с Fake LLM — **full_replace не дублирует строки**, **трансляция target_id→target_hash**, `_elements_to_text` |
|
||||
| `test_routes.py` | HTTP-эндпоинты (Flask test client): `/health`, `/api/spec-current`, `/upload`, `/unzip-upload`, `/api/groups` |
|
||||
| `test_upload_security.py` | `routes/upload_bp.py`: `_check_ext` (допустимые/недопустимые), `_unzip` (path traversal нейтрализуется, битый zip) |
|
||||
|
||||
## Ключевые проверки
|
||||
|
||||
- `test_full_replace_no_duplicates` — два `full_replace` подряд → в `spec_current` 3 строки, а не 6; история `spec_events` (6 событий) сохранена.
|
||||
- `test_update_applies` — `target_id: "r1"` транслируется в `target_hash` → UPDATE применяется (status `applied`), а не уходит в UNRESOLVED.
|
||||
- `test_path_traversal_neutralized` — `../etc/passwd` внутри ZIP → имя файла `passwd` без пути.
|
||||
|
||||
## Изоляция
|
||||
|
||||
- Каждый тест, работающий с БД, получает свою копию SQLite через фикстуру `db`
|
||||
(monkeypatch `DB_PATH` → `tmp_path`, `init_db()`).
|
||||
- LLM-вызовы в пайплайне подменяются через `monkeypatch.setattr("services.llm.call_llm", ...)` — сеть не используется.
|
||||
@@ -11,7 +11,8 @@ class TestPgToSqlite:
|
||||
assert "::jsonb" not in out
|
||||
|
||||
def test_boolean(self):
|
||||
out = _pg_to_sqlite("CREATE TABLE t (flag BOOLEAN)")
|
||||
# " BOOLEAN " заменяется только когда после слова идёт пробел
|
||||
out = _pg_to_sqlite("CREATE TABLE t (flag BOOLEAN NOT NULL)")
|
||||
assert "BOOLEAN" not in out
|
||||
assert "INTEGER" in out
|
||||
|
||||
|
||||
Reference in New Issue
Block a user