Загрузка данных


мод во тест 

удленное есть весь класс с заменой
@dataclass
class BaseSuiteConfig:
    """
    Структура:
    1. Метаданные набора (имя, id, архив)
    2. Технологический участок (из enum TU)
    """

    # ===== Метаданные набора =====
    suite_name: str
    suite_data_id: int
    archive_name: str = ""  # Автоматически вычисляется из suite_name

    # ===== Технологический участок =====
    technological_unit: TU = TU.TIKHORETSK_NOVOROSSIYSK_3

    # ===== LDS Configurator (Администрирование) =====
    use_lds_configurator: bool = False
    admin_tu_name: str = ""
    resolved_tu_id: Optional[int] = None

    # ===== Правила конвертации единиц измерения давления на стенде =====
    measure_conversion_rules: Optional[MeasureConversionRule] = None

    # ===== Общие константы (можно переопределить) =====
    allowed_distance_diff_meters: int = BaseTN3Constants.ALLOWED_DISTANCE_DIFF_METERS
    precision: int = BaseTN3Constants.PRECISION
    basic_message_timeout: float = BaseTN3Constants.BASIC_MESSAGE_TIMEOUT
    mask_message_timeout: float = BaseTN3Constants.MASK_MESSAGE_TIMEOUT
    mask_du_name: Optional[str] = None
    main_pipe_line: Optional[str] = None
    mask_du_event: Optional[str] = None
    unmask_du_event: Optional[str] = None

    # ===== Свойства для удобства =====
    @property
    def tu_name(self) -> str:
        """Имя ТУ для бизнес-тестов (журнал, BasicInfo) — из enum TU."""
        return self.technological_unit.description

    @property
    def tu_id(self) -> int:
        """ID технологического участка из enum TU (имитатор, WS-тесты)."""
        return self.technological_unit.id

    @property
    def configurator_tu_id(self) -> int:
        """tuId из Администрирования после infra setup (LaunchLds/StopLds)."""
        if self.resolved_tu_id is None:
            raise RuntimeError(
                "resolved_tu_id не установлен — выполните lds_configurator_admin_setup перед операциями Администрирования"
            )
        return self.resolved_tu_id

    @property
    def infra_tu_id(self) -> int:
        """legacy: id ТУ для инфра-setup (имитатор, tags.txt, file_name)."""
        return self.technological_unit.id

    @property
    def has_multiple_leaks(self) -> bool:
        return False
















тест конст
    MAIN_PAGE_SYNC_TIMEOUT_SECONDS: float = 30.0
    LAUNCHED_AT_TOLERANCE_SECONDS: float = 120.0











датасет
SELECT_6_CONFIG = SmokeSuiteConfig(
    # ===== Метаданные =====
    suite_name=SUITE_NAME,
    suite_data_id=SUITE_DATA_ID,
    archive_name=ARCHIVE_NAME,
    technological_unit=TECHNOLOGICAL_UNIT,
    main_pipeline=MAIN_PIPELINE,
    # ===== LDS Configurator =====
    use_lds_configurator=True,
    admin_tu_name="Тихорецк-Новороссийск-3-Автотест",




















test_scenarios\lds_configurator_scenarios.py
"""
Сценарии setup/teardown СОУ через раздел Администрирование (LDS Configurator).
"""

from __future__ import annotations

import logging
from typing import Any, Dict, Optional

from pytest import fail

from clients.websocket_client import WebSocketClient
from constants.enums import SouAdminStatus
from constants.test_constants import LdsConfiguratorConstants as LdsCfgConst
from test_config.models_for_tests import BaseSuiteConfig
from utils.helpers import lds_configurator_utils as lds_utils
from utils.helpers import ws_test_utils as t_utils
from utils.helpers.ws_message_parser import ws_message_parser as parser

logger = logging.getLogger(__name__)


def _save_group_state(group_state: Optional[Dict[str, Any]], cfg: BaseSuiteConfig, tu_id: int) -> None:
    """
    Сохраняет resolved tu_id и флаги в group_state для teardown в conftest.
    """
    if group_state is None:
        return
    group_state["use_lds_configurator"] = cfg.use_lds_configurator
    group_state["resolved_tu_id"] = tu_id
    group_state["admin_tu_name"] = cfg.admin_tu_name


async def lds_configurator_admin_setup(
    ws_client: WebSocketClient,
    cfg: BaseSuiteConfig,
    group_state: Optional[Dict[str, Any]] = None,
) -> None:
    """
    Холодный запуск СОУ через Администрирование до старта имитатора.

    1. Получить tu_id по admin_tu_name из GetBasicInfoAdmin.
    2. При необходимости остановить уже запущенную СОУ.
    3. LaunchLdsRequest и ожидание status=включена.
    4. Подтвердить launchedAt в GetTusInformation.
    """
    tu_id: int
    sou_status: SouAdminStatus

    logger.info("[SETUP] Получение ТУ '%s' из Администрирования", cfg.admin_tu_name)
    admin_reply = await lds_utils.get_basic_info_admin_with_retry(ws_client, parser)
    admin_tu = lds_utils.find_tu_by_name(admin_reply, cfg.admin_tu_name)
    lds_utils.validate_admin_tu(admin_tu)
    sou_status = SouAdminStatus(admin_tu.status)
    tu_id = admin_tu.tuId
    cfg.resolved_tu_id = tu_id
    _save_group_state(group_state, cfg, tu_id)
    logger.info(
        "[SETUP] Найден ТУ: tuId=%s, tuName=%r, status=%s (%s)",
        tu_id,
        admin_tu.tuName,
        sou_status,
        SouAdminStatus.report_text_by_value(admin_tu.status),
    )

    if sou_status == SouAdminStatus.RUNNING:
        logger.info("[SETUP] Остановка СОУ перед холодным запуском (уже была включена)")
        await lds_utils.invoke_lds_command(ws_client, parser, LdsCfgConst.STOP_LDS_REQUEST, tu_id)
        if not await lds_utils.poll_admin_tu_status(ws_client, parser, tu_id, SouAdminStatus.STOPPED):
            fail(
                "Не удалось перезапустить СОУ: статус в Администрировании не стал 'выключена' за 2 минуты",
                pytrace=False,
            )

    launch_checkpoint = t_utils.moscow_now()
    logger.info(
        "[SETUP] Момент фиксации времени перед LaunchLds: %s",
        t_utils.format_datetime_moscow(launch_checkpoint),
    )

    logger.info("[SETUP] Холодный запуск СОУ (LaunchLdsRequest) для tuId=%s", tu_id)
    await lds_utils.invoke_lds_command(ws_client, parser, LdsCfgConst.LAUNCH_LDS_REQUEST, tu_id)

    logger.info("[SETUP] Ожидание включения СОУ в Администрировании")
    if not await lds_utils.poll_admin_tu_status(ws_client, parser, tu_id, SouAdminStatus.RUNNING):
        fail(
            "Не удалось запустить СОУ: статус в Администрировании не стал 'включена' за 2 минуты",
            pytrace=False,
        )

    logger.info("[SETUP] Подтверждение времени запуска (GetTusInformation)")
    await lds_utils.verify_launched_at(ws_client, parser, tu_id, launch_checkpoint)


async def lds_configurator_verify_after_core(
    ws_client: WebSocketClient,
    cfg: BaseSuiteConfig,
) -> None:
    """
    Проверка готовности стенда после запуска lds-core.

    1. Актуальный статус СОУ из Администрирования.
    2. Сверка с Состоянием МТ (MainPageInfoContent).
    3. Ожидание появления ТУ в Состоянии МТ при status=включена.
    """
    tu_id = cfg.configurator_tu_id

    logger.info("[SETUP] Получение актуального статуса СОУ для tuId=%s", tu_id)
    admin_reply = await lds_utils.get_basic_info_admin_with_retry(ws_client, parser)
    sou_status = lds_utils.get_admin_tu_status(admin_reply, tu_id)
    if sou_status is None:
        fail(
            f"ТУ tuId={tu_id} ('{cfg.admin_tu_name}') не найден в GetBasicInfoAdminResponse",
            pytrace=False,
        )

    logger.info("[SETUP] Сверка статуса СОУ: Администрирование vs Состояние МТ")
    is_on_main_page = await lds_utils.is_tu_present_on_main_page(ws_client, parser, tu_id)
    lds_utils.check_sou_status_sync(sou_status, is_on_main_page, tu_id, cfg.admin_tu_name)

    if sou_status == SouAdminStatus.RUNNING:
        logger.info("[SETUP] Ожидание появления ТУ в Состоянии МТ")
        if not await lds_utils.poll_main_page_tu_presence(ws_client, tu_id, expect_present=True):
            fail(
                "СОУ не отображается в Состоянии МТ: ТУ не появилась за 2 минуты после запуска core",
                pytrace=False,
            )


async def lds_configurator_teardown(
    ws_client: WebSocketClient,
    tu_id: int,
    admin_tu_name: str,
) -> None:
    """
    Teardown набора: остановка СОУ после прогона.

    Некритичные отклонения логируются без падения прогона.
    """
    logger.info("[TEARDOWN] Проверка статуса СОУ (tuId=%s, «%s»)", tu_id, admin_tu_name)
    try:
        admin_reply = await lds_utils.get_basic_info_admin(ws_client, parser)
    except Exception as error:
        lds_utils.attach_allure_alert(
            f"Не удалось получить статус СОУ при teardown: {error}. "
            f"tuId={tu_id}, adminTuName={admin_tu_name!r}"
        )
        return

    sou_status = lds_utils.get_admin_tu_status(admin_reply, tu_id)
    if sou_status != SouAdminStatus.RUNNING:
        lds_utils.attach_allure_alert(
            f"СОУ не в статусе 'включена' при teardown (status={sou_status}), остановка пропущена. "
            f"tuId={tu_id}, adminTuName='{admin_tu_name}'"
        )
        return

    logger.info("[TEARDOWN] Остановка СОУ (StopLdsRequest) для tuId=%s", tu_id)
    try:
        await lds_utils.invoke_lds_command(ws_client, parser, LdsCfgConst.STOP_LDS_REQUEST, tu_id)
    except Exception as error:
        lds_utils.attach_allure_alert(
            f"Ошибка при StopLdsRequest: {error}. tuId={tu_id}, adminTuName={admin_tu_name!r}"
        )
        return

    logger.info("[TEARDOWN] Ожидание выключения СОУ в Администрировании")
    if not await lds_utils.poll_admin_tu_status(ws_client, parser, tu_id, SouAdminStatus.STOPPED):
        lds_utils.attach_allure_alert(
            f"СОУ не выключилась за 2 минуты после StopLdsRequest. "
            f"tuId={tu_id}, adminTuName={admin_tu_name!r}. Проверить вручную."
        )











конфтест
from test_scenarios import lds_configurator_scenarios
from utils.helpers import lds_configurator_utils as lds_cfg_utils





        "resolved_tu_id": None,
        "admin_tu_name": None,
        "suite_infra_ready": False,



удалить:
    'test_lds_configurator_verify': 'lds_configurator_verify_test',

    'test_lds_configurator_verify': 'lds_configurator_verify_test',

        if test_name == 'test_lds_configurator_verify':
            suite_config = params['config']
            if not suite_config.use_lds_configurator:
                return None
            if not suite_config.tu_name.strip():
                pytest.fail(
                    f"Набор '{suite_config.suite_name}': tu_name обязателен к заполнению в датасете набора при use_lds_configurator=True"
                )
            return suite_config.lds_configurator_verify_test






        pytest.fail(
            "Не удалось вычислить imitator_duration: в тестовом модуле одновременно отсутствуют "
            "и @pytest.mark.offset(), и pytest.mark.imitator_duration()"
        )


@pytest.fixture(autouse=True)
def require_suite_infra(request):
    """
    Блокирует тесты набора, если infra-setup не завершился успешно.
    """
    if not request.node.get_closest_marker("test_suite_name"):
        return
    cfg = request.config.group_state
    if cfg.get("current_suite") and not cfg.get("suite_infra_ready"):
        pytest.exit(
            "[SETUP] [ERROR] Инфраструктура набора не готова (suite_infra_ready=False). "
            "Тесты не запускаются."
        )






        # stop old
        _run_lds_configurator_teardown_if_needed(cfg)






        cfg["suite_start_time"] = None
        cfg["suite_infra_ready"] = False






        measure_conversion_rules = suite_config.measure_conversion_rules if suite_config is not None else None

        if suite_config is not None and suite_config.use_lds_configurator:
            if not suite_config.admin_tu_name.strip():
                pytest.exit(
                    f"[SETUP] [ERROR] Набор '{suite_config.suite_name}': admin_tu_name обязателен "
                    "при use_lds_configurator=True"
                )






                _run_lds_admin_setup(suite_config, cfg)
            except BaseException as error:






        # Сохраняем время старта имитатора для расчёта интервалов утечек в тестах
        cfg["imitator_start_time"] = stand_manager.start_time

        if suite_config is not None and suite_config.use_lds_configurator:
            try:
                _run_lds_verify_after_core(suite_config)
            except BaseException as error:
                pytest.exit(f"[SETUP] [ERROR] LDS Configurator проверка после запуска ядра: {error}")

        cfg["suite_infra_ready"] = True







    yield  # pytest продолжит выполнение теста


def _run_lds_infra(coro_factory) -> None:
    """Запускает async infra-сценарий с логированием вместо Allure."""
    lds_cfg_utils.set_infra_mode(True)
    try:
        asyncio.run(coro_factory())
    finally:
        lds_cfg_utils.set_infra_mode(False)








        async with WebSocketClient(ws_host, token) as client:
            await lds_configurator_scenarios.lds_configurator_admin_setup(
                client, suite_config, group_state
            )

    _run_lds_infra(_admin_setup)


def _run_lds_verify_after_core(suite_config) -> None:
    """
    WS-проверка готовности стенда после запуска lds-core.
    """
    async def _verify() -> None:
        ws_host = get_ws_host()
        token = get_token()
        async with WebSocketClient(ws_host, token) as client:
            await lds_configurator_scenarios.lds_configurator_verify_after_core(client, suite_config)

    _run_lds_infra(_verify)






    tu_id = cfg["resolved_tu_id"]
    admin_tu_name = cfg.get("admin_tu_name") or ""







        async with WebSocketClient(ws_host, token) as client:
            await lds_configurator_scenarios.lds_configurator_teardown(client, tu_id, admin_tu_name)



            await lds_configurator_scenarios.lds_configurator_teardown(client, tu_id, admin_tu_name)

    try:
        _run_lds_infra(_teardown)





        cfg["use_lds_configurator"] = False
        cfg["admin_tu_name"] = None






    if next_suite != cfg["current_suite"]:
удалить строку
        if stand_manager := cfg["stand_manager"]:









        cfg["imitator_start_time"] = None
        cfg["suite_infra_ready"] = False














тест смоук
удален импорт
from clients.websocket_client import WebSocketClient
from constants.test_constants import BaseTN3Constants as Base_const
from test_config.datasets import ALL_SMOKE_CONFIGS
from test_config.models_for_tests import CaseMarkers, LeakTestConfig, SmokeSuiteConfig
from test_scenarios import lds_status_scenarios
from test_scenarios import smoke_scenarios as scenarios






удалить     
@pytest.mark.asyncio
    @pytest.mark.critical_stop
    async def test_lds_configurator_verify(
        self, ws_client: WebSocketClient, config: SmokeSuiteConfig
    ) -> None:
        tag = "LdsConfigurator"
        title = f"[{tag}] Проверка наличия запускаемого ТУ  на ЭФ Состояние МТ сразу после запуска core"
        _apply_allure_markers(config.lds_configurator_verify_test, tag, title)
        await lds_configurator_scenarios.lds_configurator_verify_after_core(ws_client, config)


тетс бэйсик сделать крит стоп

















тест лдс статус регрес

удален импорт

from clients.websocket_client import WebSocketClient
from test_config.datasets import ALL_LDS_STATUS_CONFIGS
from test_config.models_for_tests import CaseMarkers, LDSStatusConfig
from test_scenarios import scenarios


удалить 
    @pytest.mark.asyncio
    @pytest.mark.critical_stop
    async def test_lds_configurator_verify(
        self, ws_client: WebSocketClient, config: LDSStatusConfig
    ) -> None:
        tag = "LdsConfigurator"
        title = f"[{tag}] Проверка наличия запускаемого ТУ  на ЭФ Состояние МТ сразу после запуска core"
        _apply_allure_markers(config.lds_configurator_verify_test, tag, title)
        await lds_configurator_scenarios.lds_configurator_verify_after_core(ws_client, config)




сделть бэйсик критом















енам
class TU(Enum):
    """Технологический участок. id - для имитатора (tn{id}_tags.txt) и WS-тестов."""