You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

203 lines
10 KiB
Python

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import unittest
import requests
import uuid
BASE_URL = "http://localhost:8091"
def get_error_message(response: requests.Response) -> str:
"""Извлекает сообщение об ошибке из ответа сервера или возвращает понятную заглушку."""
try:
if response.headers.get('Content-Type', '').startswith('application/json'):
data = response.json()
return data.get("error", "No 'error' field in JSON response")
else:
return f"Non-JSON response: {response.text[:200]}"
except Exception as e:
return f"Failed to parse error: {e} | Raw: {response.text[:200]}"
class TestGameShopAPI(unittest.TestCase):
valid_token = None
test_nickname = "autotest_user"
test_password = "secure_password_123"
test_email = "autotest@example.com"
@classmethod
def setUpClass(cls):
"""Регистрируем пользователя один раз перед всеми тестами."""
super().setUpClass()
register_payload = {
"nickname": cls.test_nickname,
"password": cls.test_password,
"email": cls.test_email
}
try:
response = requests.post(f"{BASE_URL}/register/", json=register_payload, timeout=10)
if response.status_code != 200:
error_msg = get_error_message(response)
raise RuntimeError(f"Registration failed ({response.status_code}): {error_msg}")
data = response.json()
cls.valid_token = data.get("success")
if not cls.valid_token:
raise ValueError("Response missing 'success' field with token")
uuid.UUID(cls.valid_token)
except Exception as e:
raise unittest.SkipTest(f"Не удалось зарегистрировать пользователя: {e}")
@classmethod
def tearDownClass(cls):
"""Удаляем пользователя после всех тестов."""
if cls.valid_token:
try:
headers = {"Authorization": "Bearer " + cls.valid_token}
response = requests.post(f"{BASE_URL}/unregister/", headers=headers, timeout=10)
if response.status_code != 200:
error_msg = get_error_message(response)
print(f"⚠️ Внимание: unregister завершился с кодом {response.status_code}: {error_msg}")
except Exception as e:
print(f"⚠️ Ошибка при unregister: {e}")
super().tearDownClass()
def test_1_get_shop_products(self):
"""GET /shop/ — должен вернуть непустой список товаров"""
response = requests.get(f"{BASE_URL}/shop/")
if response.status_code != 200:
error_msg = get_error_message(response)
self.fail(f"GET /shop/ failed ({response.status_code}): {error_msg}")
data = response.json()
self.assertIn("success", data, f"Ответ не содержит 'success'. Получено: {data}")
products = data["success"]
self.assertIsInstance(products, list, f"'success' должен быть списком, получено: {type(products)}")
self.assertGreater(len(products), 0, "Список товаров пуст")
product = products[0]
required = {"id", "name", "count", "reserved", "picture_url", "description", "type", "cost"}
missing = required - set(product.keys())
self.assertFalse(missing, f"В товаре отсутствуют поля: {missing}. Товар: {product}")
self.assertIsInstance(product["cost"], (int, float), f"'cost' должен быть числом, получено: {type(product['cost'])}")
def test_2_registration_returns_valid_token(self):
"""Проверка, что токен — валидный UUID"""
self.assertIsNotNone(self.valid_token, "Токен не был получен при регистрации")
try:
uuid.UUID(self.valid_token)
except ValueError:
self.fail(f"Токен не является валидным UUID: {self.valid_token}")
def test_3_basket_success(self):
"""POST /basket/ с валидным токеном → возвращает '[]'"""
headers = {"Authorization": "Bearer " + self.valid_token}
response = requests.post(f"{BASE_URL}/basket/", headers=headers)
if response.status_code != 200:
error_msg = get_error_message(response)
self.fail(f"POST /basket/ failed ({response.status_code}): {error_msg}")
data = response.json()
self.assertIn("success", data, f"Ответ не содержит 'success'. Получено: {data}")
self.assertEqual(data["success"], [], f"Ожидалась пустая корзина ([]), получено: {data['success']}")
def test_4_history_success(self):
"""POST /history/ с валидным токеном → возвращает '[]'"""
headers = {"Authorization": "Bearer " + self.valid_token}
response = requests.post(f"{BASE_URL}/history/", headers=headers)
if response.status_code != 200:
error_msg = get_error_message(response)
self.fail(f"POST /history/ failed ({response.status_code}): {error_msg}")
data = response.json()
self.assertIn("success", data, f"Ответ не содержит 'success'. Получено: {data}")
self.assertEqual(data["success"], [], f"Ожидалась пустая история ([]), получено: {data['success']}")
def test_5_basket_invalid_token(self):
"""POST /basket/ с невалидным токеном → ошибка 500"""
headers = {"Authorization": "Bearer " + "invalid-token-12345"}
response = requests.post(f"{BASE_URL}/basket/", headers=headers)
if response.status_code != 500:
error_msg = get_error_message(response)
self.fail(f"Ожидался статус 500 для невалидного токена, получен {response.status_code}. Ошибка: {error_msg}")
data = response.json()
self.assertIn("error", data, f"Ответ должен содержать 'error', получено: {data}")
self.assertIsInstance(data["error"], str, f"'error' должен быть строкой, получено: {type(data['error'])}")
self.assertGreater(len(data["error"]), 0, "Сообщение об ошибке пустое")
def test_6_history_invalid_token(self):
"""POST /history/ с невалидным токеном → ошибка 500"""
headers = {"Authorization": "Bearer " + "invalid-token-12345"}
response = requests.post(f"{BASE_URL}/history/", headers=headers)
if response.status_code != 500:
error_msg = get_error_message(response)
self.fail(f"Ожидался статус 500 для невалидного токена, получен {response.status_code}. Ошибка: {error_msg}")
data = response.json()
self.assertIn("error", data, f"Ответ должен содержать 'error', получено: {data}")
def test_7_login_success(self):
"""POST /login/ — успешная аутентификация зарегистрированного пользователя"""
login_payload = {
"email": self.test_email,
"password": self.test_password
}
response = requests.post(f"{BASE_URL}/login/", json=login_payload)
if response.status_code != 200:
error_msg = get_error_message(response)
self.fail(f"POST /login/ failed ({response.status_code}): {error_msg}")
data = response.json()
self.assertIn("success", data, f"Ответ не содержит 'OK'. Получено: {data}")
login_token = data["success"]
try:
uuid.UUID(login_token)
except ValueError:
self.fail(f"Токен от /login/ не является валидным UUID: {login_token}")
# Проверка, что токен работает
basket_resp = requests.post(f"{BASE_URL}/basket/", headers={"Authorization": "Bearer " + login_token})
if basket_resp.status_code != 200:
error_msg = get_error_message(basket_resp)
self.fail(f"Токен от /login/ не работает: {error_msg}")
def test_8_user_success(self):
"""POST /user/ с валидным токеном → возвращает данные пользователя"""
headers = {"Authorization": "Bearer " + self.valid_token}
response = requests.post(f"{BASE_URL}/user/", headers=headers)
if response.status_code != 200:
error_msg = get_error_message(response)
self.fail(f"POST /user/ failed ({response.status_code}): {error_msg}")
data = response.json()
self.assertIn("success", data, f"Ответ не содержит 'success'. Получено: {data}")
user_data = data["success"][0]
required_fields = {"id", "nickname", "email", "token", "money", "histories_id"}
missing = required_fields - set(user_data.keys())
self.assertFalse(missing, f"В данных пользователя отсутствуют поля: {missing}")
self.assertEqual(user_data["nickname"], self.test_nickname)
self.assertEqual(user_data["email"], self.test_email)
self.assertIsInstance(float(user_data["money"]), float)
self.assertIsInstance(user_data["histories_id"], list)
def test_9_logout_success(self):
"""POST /logout/ с валидным токеном — успешный выход"""
headers = {"Authorization": "Bearer " + self.valid_token}
response = requests.post(f"{BASE_URL}/logout/", headers=headers)
if response.status_code != 200:
error_msg = get_error_message(response)
self.fail(f"POST /logout/ failed ({response.status_code}): {error_msg}")
data = response.json()
self.assertIn("success", data, f"Ответ не содержит 'OK'. Получено: {data}")
self.assertEqual(data["success"], self.valid_token, "В ответе должен быть тот же токен")
def test_10_all_scenarios_completed(self):
"""Финальная проверка: все тесты пройдены"""
pass
if __name__ == "__main__":
unittest.main(verbosity=2)