Noob_test/tests/TesFindPlaceInfo.py
2026-04-06 14:06:27 +03:00

114 lines
5.2 KiB
Python
Raw 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.

"""Проверка ответа GraphQL place: структура и значения полей results[ ] + Allure-отчёт."""
from __future__ import annotations
import json
from typing import Any, Final
import allure # pyright: ignore[reportMissingImports]
import pytest
from allure_commons.types import AttachmentType # pyright: ignore[reportMissingImports]
from worklib.findplaceinfo.find_place_data import fetch_place_members
# Ожидаемый фрагмент ответа (ключи и значения должны совпадать хотя бы в одной записи results).
_EXPECTED_RESULT: Final[dict[str, str]] = {
"id": "682b071a163ac2a0995355be",
"place_type": "street",
"name": "ул. Мебельная",
}
ALLURE_EPIC = "Place API"
ALLURE_FEATURE = "GraphQL place"
ALLURE_STORY = "Формат ответа и значения полей"
@allure.epic(ALLURE_EPIC)
@allure.feature(ALLURE_FEATURE)
@allure.story(ALLURE_STORY)
@pytest.mark.integration
class TestFindPlaceInfo:
"""Интеграционный тест: реальный запрос и сверка формата/значений."""
@pytest.fixture(scope="class")
def place_response(self) -> dict[str, Any]:
with allure.step("Запрос place через GraphQL (fetch_place_members)"):
payload = fetch_place_members()
allure.attach(
json.dumps(payload, ensure_ascii=False, indent=2),
name="Ответ GraphQL (raw JSON)",
attachment_type=AttachmentType.JSON,
)
return payload
@allure.title("Структура: data → place → results[] с полями id, place_type, name")
@allure.severity(allure.severity_level.NORMAL)
def test_response_has_place_shape(self, place_response: dict[str, Any]) -> None:
with allure.step("Проверка вложенности data.place.results"):
results = _extract_results(place_response)
allure.attach(
json.dumps(results, ensure_ascii=False, indent=2),
name="results (извлечено)",
attachment_type=AttachmentType.JSON,
)
assert len(results) >= 1, "results должен содержать хотя бы один элемент"
for key in ("id", "place_type", "name"):
assert key in results[0], f'В элементе results[0] должен быть ключ "{key}"'
@allure.title("Значения id, place_type, name совпадают с эталоном")
@allure.severity(allure.severity_level.CRITICAL)
def test_expected_id_place_type_name_match(self, place_response: dict[str, Any]) -> None:
allure.attach(
json.dumps(_EXPECTED_RESULT, ensure_ascii=False, indent=2),
name="Ожидаемый объект в results",
attachment_type=AttachmentType.JSON,
)
with allure.step("Поиск записи с полным совпадением id, place_type, name"):
results = _extract_results(place_response)
match = _find_matching_result(results, _EXPECTED_RESULT)
if match is None:
allure.attach(
json.dumps(results, ensure_ascii=False, indent=2),
name="Фактический results (для отладки)",
attachment_type=AttachmentType.JSON,
)
assert match is not None, (
f"Ни одна запись в results не совпадает с ожидаемым набором {_EXPECTED_RESULT}. "
f"Получено: {json.dumps(results, ensure_ascii=False, indent=2)[:2000]}"
)
allure.attach(
json.dumps(match, ensure_ascii=False, indent=2),
name="Найденная запись",
attachment_type=AttachmentType.JSON,
)
assert match["id"] == _EXPECTED_RESULT["id"]
assert match["place_type"] == _EXPECTED_RESULT["place_type"]
assert match["name"] == _EXPECTED_RESULT["name"]
def _extract_results(payload: dict[str, Any]) -> list[dict[str, Any]]:
assert "data" in payload, f'В ответе нет ключа "data": {json.dumps(payload, ensure_ascii=False)[:500]}'
data = payload["data"]
assert isinstance(data, dict), '"data" должен быть объектом'
assert "place" in data, f'В data нет "place": keys={list(data.keys())}'
place = data["place"]
assert place is not None, '"place" не должен быть null'
assert isinstance(place, dict), '"place" должен быть объектом'
assert "results" in place, f'В place нет "results": keys={list(place.keys())}'
results = place["results"]
assert isinstance(results, list), '"results" должен быть массивом'
for i, item in enumerate(results):
assert isinstance(item, dict), f'results[{i}] должен быть объектом, получено {type(item)}'
return results
def _find_matching_result(results: list[dict[str, Any]], expected: dict[str, str]) -> dict[str, Any] | None:
for item in results:
if all(item.get(k) == v for k, v in expected.items()):
return item
return None