Загрузка данных
сценарий имитат плс маск замена
async def imitate_sensor_signal(
ws_client, http_client, cfg: SmokeSuiteConfig, test_data: CaseData, imitator_start_time
):
"""
Проверка имитации сигнала датчика.
"""
# Распаковка данных для теста
sensor_address = test_data.params.get("sensor_address")
sensor_val, sensor_quality, imitation_event, unimitation_event = test_data.expected_result
# Получение актуального id датчика
sensor_id = TestConst.SENSOR_IDS_BY_ADDRESS.get(sensor_address)
with allure.step(f"Http запрос и обработка ответа об имитации сигнала датчика с id: {sensor_id}"):
request_body = {
'id': sensor_id,
'tuId': cfg.tu_id,
'imitateInfo': {'value': str(sensor_val), 'quality': sensor_quality},
}
response = http_client.post_request(HttpConst.IMITATE_SIGNAL_URL_PATH, request_body)
sensor_imitate_reply_status = response.status_code
StepCheck("Проверка кода ответа на запрос об имитации", "replyStatus").actual(
sensor_imitate_reply_status
).expected(ReplyStatus.OK.value).equal_to()
with allure.step("Подключение по ws и http, получение и обработка данных сообщений для проверки имитации"):
with allure.step(
"Получение данных для проверки имитации. Тип сообщения: InputSignalsContent. ЭФ Диагностика Сигналов."
):
parsed_payload, imitate_elapsed = await t_utils.poll_input_signal_state(
ws_client,
[sensor_id],
"isImitated",
True,
{'signalIds': [sensor_id], 'tuId': cfg.tu_id, 'additionalProperties': None},
)
with allure.step(f"Имитация установилась за {imitate_elapsed:.0f} сек"):
pass
with allure.step(
"Подготовка данных для проверки имитации. Тип сообщения: InputSignalsContent. ЭФ Диагностика Сигналов."
):
sensor_data = getattr(parsed_payload.replyContent, 'inputSignals', [])
diagnostics_sensor_imitate_data = t_utils.find_object_by_field(sensor_data, "id", sensor_id)
value_diagnostics_sensor_imitate = getattr(
getattr(diagnostics_sensor_imitate_data, 'imitation', []), 'value', []
)
is_imitated_diagnostics_sensor_imitate = getattr(diagnostics_sensor_imitate_data, 'isImitated', [])
quality_diagnostics_sensor_imitate = getattr(diagnostics_sensor_imitate_data, 'quality', [])
with allure.step("Получение данных для проверки имитации. Тип сообщения: SchemeSignalsStateContent. ЭФ Схема."):
payload = await t_utils.connect_and_poll_subscribed_msg(
ws_client,
"SchemeSignalsStateContent",
"SubscribeSchemeSignalsStateRequest",
{'tuId': cfg.tu_id},
)
parsed_payload = parser.parse_scheme_signals_state_msg(payload)
journal_signal_state_list = parsed_payload.replyContent.signalsStates
scheme_sensor_imitate_data = t_utils.find_object_by_field(journal_signal_state_list, "id", sensor_id)
is_imitated_scheme_sensor_imitate = getattr(scheme_sensor_imitate_data, 'isImitated', [])
with allure.step(f"Http запрос и обработка ответа о снятии имитации датчика с id: {sensor_id}"):
request_body = {'id': sensor_id, 'tuId': cfg.tu_id}
response = http_client.post_request(HttpConst.UNIMITATE_SIGNAL_URL_PATH, request_body)
sensor_unimitate_reply_status = response.status_code
StepCheck("Проверка кода ответа на запрос о снятии имитации", "replyStatus").actual(
sensor_unimitate_reply_status
).expected(ReplyStatus.OK.value).equal_to()
with allure.step("Подключение по ws и http, получение и обработка данных сообщений для проверки снятия имитации"):
with allure.step(
"Получение данных для проверки снятия имитации. InputSignalsContent. ЭФ Диагностика Сигналов."
):
parsed_payload, unimitate_elapsed = await t_utils.poll_input_signal_state(
ws_client,
[sensor_id],
"isImitated",
False,
{'signalIds': [sensor_id], 'tuId': cfg.tu_id, 'additionalProperties': None},
)
with allure.step(f"Имитация снялась за {unimitate_elapsed:.0f} сек"):
pass
with allure.step("Извлечение и подготовка данных для проверки снятия имитации"):
sensor_data = getattr(parsed_payload.replyContent, 'inputSignals', [])
diagnostics_sensor_unimitate_data = t_utils.find_object_by_field(sensor_data, 'id', sensor_id)
is_unimitated_diagnostics_sensor_unimitate = getattr(diagnostics_sensor_unimitate_data, 'isImitated', [])
with allure.step(
"Получение данных для проверки снятия имитации. Тип сообщения: SchemeSignalsStateContent. ЭФ Схема"
):
payload = await t_utils.connect_and_poll_subscribed_msg(
ws_client,
"SchemeSignalsStateContent",
"SubscribeSchemeSignalsStateRequest",
{'tuId': cfg.tu_id},
)
parsed_payload = parser.parse_scheme_signals_state_msg(payload)
journal_signal_state_list = parsed_payload.replyContent.signalsStates
scheme_sensor_unimitate = t_utils.find_object_by_field(journal_signal_state_list, "id", sensor_id)
is_unimitated_scheme_sensor_unimitate = getattr(scheme_sensor_unimitate, 'isImitated', [])
with allure.step("Http запрос сообщений журнала с фильтром userActions"):
# Запрос сообщений по типу действий пользователя маскирование и имитация сигналов
request_body = t_utils.create_journal_req_body(
pagination=Pagination(limit=TestConst.JOURNAL_PAGINATION_LIMIT, direction=Direction.FIRST.value),
filtering=Filtering(
userActions=int(UserActions.SIGNAL_MASK_SIM), objects=FilteringObjects(tuId=cfg.tu_id)
),
)
response = http_client.post_request(HttpConst.GET_MESSAGES_URL_PATH, request_body)
payload = t_utils.get_json_from_http_response(response)
parsed_payload = parser.parse_journal_msg(payload)
messages_info = getattr(parsed_payload.replyContent, 'messagesInfo', [])
# Фильтр полученных сообщений по времени
end_time = datetime.now()
filter_start_msk = t_utils.localize_as_moscow(imitator_start_time)
filter_end_msk = t_utils.localize_as_moscow(end_time)
filter_time_messages = [
msg
for msg in messages_info
if filter_start_msk <= t_utils.ensure_moscow_timezone(msg.time) <= filter_end_msk
]
filter_by_imitation_messages = [
msg
for msg in filter_time_messages
if getattr(msg, "event", None) == imitation_event and getattr(msg, "tag", None) == sensor_address
]
filter_by_unimitation_messages = [
msg
for msg in filter_time_messages
if getattr(msg, "event", None) == unimitation_event and getattr(msg, "tag", None) == sensor_address
]
with SoftAssertions() as soft_failures:
StepCheck(
f"Проверка имитации датчика с id: {sensor_id}. ЭФ Диагностика Сигналов.", "isImitated", soft_failures
).actual(is_imitated_diagnostics_sensor_imitate).expected(True).equal_to()
StepCheck(f"Проверка имитации датчика с id: {sensor_id}. ЭФ Схема.", "isImitated", soft_failures).actual(
is_imitated_scheme_sensor_imitate
).expected(True).equal_to()
StepCheck(
f"Проверка показаний датчика с id: {sensor_id}. ЭФ Диагностика Сигналов.", "value", soft_failures
).actual(value_diagnostics_sensor_imitate).expected(sensor_val).equal_to()
StepCheck(
f"Проверка качества сигнала датчика с id: {sensor_id}. ЭФ Диагностика Сигналов.", "quality", soft_failures
).actual(quality_diagnostics_sensor_imitate).expected(sensor_quality).equal_to()
StepCheck(
f"Проверка наличия сообщения с событием {imitation_event} и тегом {sensor_address}. ЭФ Журнал.",
"event",
soft_failures,
).actual(filter_by_imitation_messages).is_not_empty()
StepCheck(
f"Проверка снятия имитации датчика с id: {sensor_id}. ЭФ Диагностика Сигналов.", "isImitated", soft_failures
).actual(is_unimitated_diagnostics_sensor_unimitate).expected(False).equal_to()
StepCheck(f"Проверка снятия имитации датчика с id: {sensor_id}. ЭФ Схема.", "isImitated", soft_failures).actual(
is_unimitated_scheme_sensor_unimitate
).expected(False).equal_to()
StepCheck(
f" Проверка наличия сообщения с событием {unimitation_event} и тегом {sensor_address}. ЭФ Журнал.",
"event",
soft_failures,
).actual(filter_by_unimitation_messages).is_not_empty()
async def mask_signal_test(ws_client, http_client, cfg: SmokeSuiteConfig, test_data: CaseData):
"""
Проверка маскирования датчиков.
"""
if not test_data:
pytest.fail("Данные датчиков отсутствуют")
pressure_sensor_address = test_data.params.get("pressure_sensor_address")
flowmeter_address = test_data.params.get("flowmeter_address")
# Получение актуальных id датчиков
pressure_sensor_id = TestConst.SENSOR_IDS_BY_ADDRESS.get(pressure_sensor_address)
flowmeter_id = TestConst.SENSOR_IDS_BY_ADDRESS.get(flowmeter_address)
with allure.step("Маскирование датчиков"):
with allure.step(f"Http запрос и обработка ответа о маскировании датчика давления с id: {pressure_sensor_id}"):
request_body = {'id': pressure_sensor_id, 'tuId': cfg.tu_id}
response = http_client.post_request(HttpConst.MASK_SIGNAL_URL_PATH, request_body)
pressure_sensor_mask_reply_status = response.status_code
StepCheck("Проверка кода ответа на запрос о маскировании", "replyStatus").actual(
pressure_sensor_mask_reply_status
).expected(ReplyStatus.OK.value).equal_to()
with allure.step(f"Http запрос и обработка ответа о маскировании расходомера с id: {flowmeter_id}"):
request_body = {'id': flowmeter_id, 'tuId': cfg.tu_id}
response = http_client.post_request(HttpConst.MASK_SIGNAL_URL_PATH, request_body)
flowmeter_mask_reply_status = response.status_code
StepCheck("Проверка кода ответа на запрос о маскировании", "replyStatus").actual(
flowmeter_mask_reply_status
).expected(ReplyStatus.OK.value).equal_to()
with allure.step(
"Подключение по ws, получение и обработка данных о статусе датчиков из сообщения типа: InputSignalsContent"
):
parsed_payload, mask_elapsed = await t_utils.poll_input_signal_state(
ws_client,
[pressure_sensor_id, flowmeter_id],
"isMasked",
True,
{
'signalIds': [pressure_sensor_id, flowmeter_id],
'tuId': cfg.tu_id,
'additionalProperties': None,
},
)
with allure.step(f"Маскирование установилось за {mask_elapsed:.0f} сек"):
pass
with allure.step("Извлечение и подготовка данных для проверки маскирования"):
sensor_data = getattr(parsed_payload.replyContent, 'inputSignals', [])
pressure_sensor_mask_data = t_utils.find_object_by_field(sensor_data, "id", pressure_sensor_id)
flowmeter_mask_data = t_utils.find_object_by_field(sensor_data, "id", flowmeter_id)
with SoftAssertions() as soft_failures:
StepCheck("Проверка наличия данных о маскировании датчика давления", "inputSignals", soft_failures).actual(
pressure_sensor_mask_data
).is_not_none()
StepCheck("Проверка наличия данных о маскировании расходомера", "inputSignals", soft_failures).actual(
flowmeter_mask_data
).is_not_none()
with allure.step("Снятие маскирования датчиков"):
with allure.step(f"Http запрос о снятии маскирования датчика давления с id: {pressure_sensor_id}"):
request_body = {'id': pressure_sensor_id, 'tuId': cfg.tu_id}
response = http_client.post_request(HttpConst.UNMASK_SIGNAL_URL_PATH, request_body)
pressure_sensor_unmask_reply_status = response.status_code
StepCheck("Проверка кода ответа на запрос о снятии маскирования", "replyStatus").actual(
pressure_sensor_unmask_reply_status
).expected(ReplyStatus.OK.value).equal_to()
with allure.step(f"Http запрос о снятии маскирования расходомера с id: {flowmeter_id}"):
request_body = {'id': flowmeter_id, 'tuId': cfg.tu_id}
response = http_client.post_request(HttpConst.UNMASK_SIGNAL_URL_PATH, request_body)
flowmeter_unmask_reply_status = response.status_code
StepCheck("Проверка кода ответа на запрос о снятии маскирования", "replyStatus").actual(
flowmeter_unmask_reply_status
).expected(ReplyStatus.OK.value).equal_to()
with allure.step(
"Подключение по ws, получение и обработка данных о статусе датчиков из сообщения типа: InputSignalsContent"
):
parsed_payload, unmask_elapsed = await t_utils.poll_input_signal_state(
ws_client,
[pressure_sensor_id, flowmeter_id],
"isMasked",
False,
{
'signalIds': [pressure_sensor_id, flowmeter_id],
'tuId': cfg.tu_id,
'additionalProperties': None,
},
)
with allure.step(f"Маскирование снялось за {unmask_elapsed:.0f} сек"):
pass
with allure.step("Извлечение и подготовка данных для проверки снятия маскирования"):
sensor_data = getattr(parsed_payload.replyContent, 'inputSignals', [])
pressure_sensor_unmask_data = t_utils.find_object_by_field(sensor_data, "id", pressure_sensor_id)
flowmeter_unmask_data = t_utils.find_object_by_field(sensor_data, "id", flowmeter_id)
with SoftAssertions() as soft_failures:
StepCheck(
"Проверка наличия данных о снятии маскировании датчика давления", "inputSignals", soft_failures
).actual(pressure_sensor_unmask_data).is_not_none()
StepCheck(
"Проверка наличия данных о снятии маскировании расходомера", "inputSignals", soft_failures
).actual(flowmeter_unmask_data).is_not_none()
with SoftAssertions() as soft_failures:
StepCheck(
f"Проверка маскирования датчика давления с id: {pressure_sensor_id}", "isMasked", soft_failures
).actual(pressure_sensor_mask_data.isMasked).expected(True).equal_to()
StepCheck(f"Проверка маскирования расходомера с id: {flowmeter_id}", "isMasked", soft_failures).actual(
flowmeter_mask_data.isMasked
).expected(True).equal_to()
StepCheck(
f"Проверка снятия маскирования датчика давления с id: {pressure_sensor_id}", "isMasked", soft_failures
).actual(pressure_sensor_unmask_data.isMasked).expected(False).equal_to()
StepCheck(f"Проверка снятия маскирования расходомера с id: {flowmeter_id}", "isMasked", soft_failures).actual(
flowmeter_unmask_data.isMasked
).expected(False).equal_to()
вс тетс утил
ws_client.suppress_recv_logging = False
async def poll_input_signal_state(
ws_client: WebSocketClient,
sensor_ids: list[int],
flag_field: str,
expected_value: bool,
ws_invoke_params: Any,
*,
attempts: int = TestConst.SIGNAL_STATE_POLL_ATTEMPTS,
per_attempt_timeout: float = TestConst.POLL_BY_TIMEOUT_SECONDS,
) -> tuple[Any, float]:
"""Опрашивает InputSignalsContent, пока у всех sensor_ids поле flag_field не станет expected_value.
Возвращает подтверждающий parsed_payload и затраченное время (сек).
При недостижении состояния за attempts попыток завершается fail(...).
"""
start = time.monotonic()
async for payload in _receive_subscribed_messages(
ws_client,
"InputSignalsContent",
"SubscribeInputSignalsRequest",
ws_invoke_params,
attempts=attempts,
per_attempt_timeout=per_attempt_timeout,
):
parsed = ws_message_parser.parse_input_signals_info_msg(payload)
signals = getattr(parsed.replyContent, "inputSignals", []) or []
signals_by_id = {signal.id: signal for signal in signals if getattr(signal, "id", None) is not None}
if all(
sensor_id in signals_by_id
and bool(getattr(signals_by_id[sensor_id], flag_field, False)) == bool(expected_value)
for sensor_id in sensor_ids
):
return parsed, time.monotonic() - start
fail(
f"Сигналы id={sensor_ids} не перешли в состояние {flag_field}={expected_value} "
f"за {attempts} попыток (лимит ~{attempts * per_attempt_timeout} сек)"
)
async def connect_and_poll_subscribed_signal(
конст
POLL_BY_TIMEOUT_SECONDS = 10.0 # Таймаут ожидания сообщения в секундах
SIGNAL_STATE_POLL_ATTEMPTS = 12 # Число опросов состояния датчика