Files
autotest/HISTORY/2026-07-23-session-4.md

3.7 KiB

Уточнение архитектуры — изоляция операций — 2026-07-23

Принцип: каждая операция = отдельный изолированный модуль

Никаких «сервисов на все случаи». Один файл — одна операция. Максимальная независимость. Лёгкое тестирование.

Структура проекта (уточнённая)

app-autotest/
├── requirements.txt
├── run.py
├── config.py
└── app/
    ├── __init__.py                 # create_app() фабрика
    ├── api/
    │   ├── __init__.py
    │   └── http_client.py          # Только HTTP: get/post, Bearer, retry, User-Agent
    ├── operations/                 # ⭐ КАЖДАЯ ОПЕРАЦИЯ — ОТДЕЛЬНЫЙ МОДУЛЬ
    │   ├── __init__.py
    │   ├── get_services.py         # GET /services → список сервисов
    │   ├── get_service_detail.py   # GET /services/{id} → операции сервиса
    │   ├── get_operation_params.py # GET /instanceOperations/default/{id} → параметры
    │   ├── create_instance.py      # POST /instances → создать инстанс
    │   ├── run_operation.py        # POST /instanceOperations → запустить операцию
    │   ├── get_instance_state.py   # GET /instances → статус инстанса
    │   └── get_instances.py        # GET /instances → список инстансов
    ├── models/
    │   ├── __init__.py
    │   ├── db.py                   # Подключение к БД
    │   ├── test_config_repo.py     # CRUD конфигураций тестов
    │   └── test_result_repo.py     # CRUD результатов тестов
    ├── routes/
    │   ├── __init__.py
    │   ├── main.py                 # Главная страница (blueprint)
    │   ├── api_routes.py           # REST API для фронта (blueprint)
    │   └── config_routes.py        # Конфигурация тестов (blueprint)
    ├── static/
    │   ├── favicon.svg
    │   ├── logo.svg
    │   ├── style.css
    │   └── app.js
    └── templates/
        ├── base.html
        ├── index.html
        └── components/
            ├── card.html
            ├── modal.html
            └── table.html

Правила операций

  • Один файл = одна операция API (не сервис, не «класс на все случаи»)
  • Каждый модуль — чистая функция (или класс с одним публичным методом)
  • Зависимость только от http_client (через DI, не глобально)
  • Никаких перекрёстных импортов между операциями
  • Каждую операцию можно протестировать изолированно (мокнуть http_client)
  • Вход: параметры + http_client → Выход: данные или ошибка

Пример сигнатуры

# app/operations/get_services.py
def get_services(client: HttpClient) -> list[dict]:
    """Получить список всех сервисов."""
    ...

# app/operations/create_instance.py
def create_instance(client: HttpClient, service_id: int, display_name: str, params: dict) -> str:
    """Создать инстанс. Возвращает instanceUid."""
    ...