From 1f031c39f94fc5f3c1147a4fa75b6e6355357df1 Mon Sep 17 00:00:00 2001 From: admin Date: Thu, 17 Sep 2026 21:18:41 +0000 Subject: [PATCH] =?UTF-8?q?=D0=97=D0=B0=D0=B3=D1=80=D1=83=D0=B7=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D1=84=D0=B0=D0=B9=D0=BB=D1=8B=20=D0=B2=20=C2=AB?= =?UTF-8?q?tests=C2=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/__init__.py | Bin 0 -> 1024 bytes tests/conftest.py | 57 +++++++++++++++++++ tests/test_disk_crud.py | 122 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 179 insertions(+) create mode 100644 tests/__init__.py create mode 100644 tests/conftest.py create mode 100644 tests/test_disk_crud.py diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..06d7405020018ddf3cacee90fd4af10487da3d20 GIT binary patch literal 1024 ScmZQz7zLvtFd70QH3R?z00031 literal 0 HcmV?d00001 diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..78bb3e1 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,57 @@ +""" +Конфигурационный файл Pytest с фикстурами для инициализации клиента и тестовых данных. +""" + +import os +import uuid +import pytest +from dotenv import load_dotenv + +from api.disk_client import YandexDiskClient + +# Загрузка переменных окружения из .env файла +load_dotenv() + + +@pytest.fixture(scope="session") +def auth_token() -> str: + """ + Фикстура получения токена авторизации. + Проверяет наличие токена в переменных окружения. Если токен не задан, + тесты пропускаются с информативным сообщением. + """ + token = os.getenv("YANDEX_DISK_TOKEN") + if not token or token.strip() == "": + pytest.skip( + "YANDEX_DISK_TOKEN не найден в переменных окружения. " + "Задайте его в .env файле или через export YANDEX_DISK_TOKEN=..." + ) + return token.strip() + + +@pytest.fixture(scope="session") +def disk_client(auth_token: str) -> YandexDiskClient: + """ + Фикстура создания экземпляра API-клиента на всю тестовую сессию. + """ + return YandexDiskClient(token=auth_token) + + +@pytest.fixture(scope="function") +def temp_folder(disk_client: YandexDiskClient): + """ + Фикстура создания изолированной временной папки для теста. + Гарантирует удаление созданной папки после завершения теста (Teardown). + """ + unique_suffix = uuid.uuid4().hex[:8] + folder_path = f"pytest_temp_{unique_suffix}" + + # Setup: создаем папку + create_resp = disk_client.create_folder(folder_path) + assert create_resp.status_code == 201, f"Не удалось подготовить фикстуру папки: {create_resp.text}" + + # Передаем управление в тест + yield folder_path + + # Teardown: удаляем папку навсегда (мимо корзины) + disk_client.delete_resource(folder_path, permanently=True) diff --git a/tests/test_disk_crud.py b/tests/test_disk_crud.py new file mode 100644 index 0000000..eea1d71 --- /dev/null +++ b/tests/test_disk_crud.py @@ -0,0 +1,122 @@ +""" +Набор автотестов для проверки REST API Яндекс Диска. +Покрывает методы: +- PUT: создание папки (создание ресурса) +- GET: получение метаданных ресурса +- POST: публикация ресурса (открытие публичного доступа) +- DELETE: удаление ресурса (очистка) +А также негативные сценарии (дублирование, несуществующий ресурс). +""" + +import uuid +import pytest +from api.disk_client import YandexDiskClient + + +@pytest.mark.crud +class TestYandexDiskCRUD: + """Тесты на основные CRUD-операции с ресурсами Яндекс Диска.""" + + def test_create_folder_put_success(self, disk_client: YandexDiskClient): + """ + Проверка создания папки (PUT-запрос). + Ожидаемый результат: HTTP 201 Created, в ответе присутствует ссылка на созданный ресурс (href). + """ + folder_name = f"dir_create_{uuid.uuid4().hex[:8]}" + try: + response = disk_client.create_folder(folder_name) + assert response.status_code == 201, f"Ожидался 201, получено {response.status_code}: {response.text}" + + data = response.json() + assert "href" in data, "В теле ответа отсутствует поле 'href'" + assert "method" in data, "В теле ответа отсутствует поле 'method'" + assert data["method"] == "GET" + finally: + # Очистка ресурса после теста + disk_client.delete_resource(folder_name, permanently=True) + + def test_get_resource_info_get_success(self, disk_client: YandexDiskClient, temp_folder: str): + """ + Проверка получения метаданных ресурса (GET-запрос). + Ожидаемый результат: HTTP 200 OK, тип ресурса 'dir', имя совпадает с созданным. + """ + response = disk_client.get_resource_info(temp_folder) + assert response.status_code == 200, f"Ожидался 200, получено {response.status_code}: {response.text}" + + data = response.json() + assert data.get("type") == "dir", f"Ожидался тип 'dir', получено {data.get('type')}" + assert data.get("name") == temp_folder, f"Имя ресурса {data.get('name')} не совпадает с {temp_folder}" + assert "created" in data, "Поле 'created' отсутствует в метаданных" + + def test_publish_resource_post_success(self, disk_client: YandexDiskClient, temp_folder: str): + """ + Проверка публикации ресурса (POST-запрос). + Ожидаемый результат: HTTP 200 OK, у папки появляется публичный URL и ключ. + """ + response = disk_client.publish_resource(temp_folder) + assert response.status_code == 200, f"Ожидался 200, получено {response.status_code}: {response.text}" + + # Проверяем метаданные папки после публикации через GET + info_resp = disk_client.get_resource_info(temp_folder) + assert info_resp.status_code == 200 + info_data = info_resp.json() + + assert "public_url" in info_data, "После публикации поле 'public_url' отсутствует" + assert "public_key" in info_data, "После публикации поле 'public_key' отсутствует" + assert info_data["public_url"].startswith("https://"), "Публичный URL имеет некорректный формат" + + def test_delete_folder_delete_success(self, disk_client: YandexDiskClient): + """ + Проверка удаления ресурса (DELETE-запрос). + Ожидаемый результат: HTTP 204 No Content при удалении, последующий GET возвращает 404 Not Found. + """ + folder_name = f"dir_delete_{uuid.uuid4().hex[:8]}" + + # Предварительно создаем папку для последующего удаления + create_resp = disk_client.create_folder(folder_name) + assert create_resp.status_code == 201 + + # Удаление + delete_resp = disk_client.delete_resource(folder_name, permanently=True) + assert delete_resp.status_code == 204, f"Ожидался 204, получено {delete_resp.status_code}: {delete_resp.text}" + + # Проверка отсутствия ресурса + get_resp = disk_client.get_resource_info(folder_name) + assert get_resp.status_code == 404, f"Ресурс все еще существует, статус {get_resp.status_code}" + + +@pytest.mark.negative +class TestYandexDiskNegative: + """Негативные тесты для проверки корректности обработки ошибок API.""" + + def test_create_duplicate_folder_put_conflict(self, disk_client: YandexDiskClient, temp_folder: str): + """ + Повторное создание уже существующей папки. + Ожидаемый результат: HTTP 409 Conflict. + """ + response = disk_client.create_folder(temp_folder) + assert response.status_code == 409, f"Ожидался 409 Conflict, получено {response.status_code}" + data = response.json() + assert data.get("error") == "PlatformResourceAlreadyExists", f"Неожиданный код ошибки: {data.get('error')}" + + def test_get_non_existent_resource_get_not_found(self, disk_client: YandexDiskClient): + """ + Запрос метаданных несуществующего ресурса. + Ожидаемый результат: HTTP 404 Not Found. + """ + non_existent_path = f"does_not_exist_{uuid.uuid4().hex}" + response = disk_client.get_resource_info(non_existent_path) + assert response.status_code == 404, f"Ожидался 404 Not Found, получено {response.status_code}" + data = response.json() + assert data.get("error") == "DiskNotFoundError", f"Неожиданный код ошибки: {data.get('error')}" + + def test_unauthorized_access(self): + """ + Выполнение запроса с недействительным токеном. + Ожидаемый результат: HTTP 401 Unauthorized. + """ + invalid_client = YandexDiskClient(token="invalid_dummy_token_123") + response = invalid_client.get_resource_info("any_folder") + assert response.status_code == 401, f"Ожидался 401 Unauthorized, получено {response.status_code}" + data = response.json() + assert data.get("error") == "UnauthorizedError", f"Неожиданный код ошибки: {data.get('error')}"