Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.venv
.idea
32 changes: 32 additions & 0 deletions conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import requests
import pytest
from faker import Faker
from urls.urls import CREATE_USER_URL, INGREDIENTS_URL
from random import randrange


@pytest.fixture()
def user():
fake = Faker("ru_RU")
payload = {
"email": fake.email(),
"password": fake.password(),
"name": fake.name()
}
Comment on lines +10 to +15

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Можно лучше: этот участок кода повторяется в 3 местах в проекте. СОздавать объект данных лучше в отдельном модуле по типу helpers, откуда просто импортировать по необходимости

response = requests.post(CREATE_USER_URL, data=payload)
body = response.json()
return {

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Нужно исправить: отсутствует функционал удаления пользователя после выполнения тестового метода.

**payload,
"accessToken": body["accessToken"],
"refreshToken": body["refreshToken"],
}


@pytest.fixture()
def random_ingredients():
response = requests.get(INGREDIENTS_URL)
ingredients = response.json()["data"]
buns = list(filter(lambda ing: ing["type"] == "bun", ingredients))
mains = list(filter(lambda ing: ing["type"] == "main", ingredients))
sauces = list(filter(lambda ing: ing["type"] == "sauce", ingredients))
return [buns[randrange(len(buns))]["_id"], mains[randrange(len(mains))]["_id"], sauces[randrange(len(sauces))]["_id"]]
2 changes: 2 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[pytest]
pythonpath = .
18 changes: 18 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
allure-pytest==2.13.5
allure-python-commons==2.13.5
attrs==24.2.0
certifi==2024.8.30
charset-normalizer==3.4.0
exceptiongroup==1.2.2
Faker==33.0.0
idna==3.10
iniconfig==2.0.0
packaging==24.2
pluggy==1.5.0
pytest==8.3.3
python-dateutil==2.9.0.post0
requests==2.32.3
six==1.16.0
tomli==2.1.0
typing_extensions==4.12.2
urllib3==2.2.3
48 changes: 48 additions & 0 deletions tests/test_create_order.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import requests
import allure
from urls.urls import CREATE_ORDER_URL
import pytest


MESSAGE_NO_INGREDIENTS = "Ingredient ids must be provided"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Можно лучше: тексты ответов стоит хранить снаружи в data модулях для поддержания и актуализации, а тут вызывать переменные в которые они записаны



class TestCreateOrder:

@allure.title('Проверка создания заказа с авторизацией и без')
@pytest.mark.parametrize('need_auth', [True, False])
def test_can_create_order(self, user, random_ingredients, need_auth):
payload = {
"ingredients": random_ingredients
}
headers = {"Authorization": user['accessToken']} if need_auth else {}

@ShamilovR ShamilovR Jan 12, 2025

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Нужно исправить: if, else в тестовых сценариях недопустимы, т.к. условия предполагают разные варианты исхода. А значит это должны быть два отдельных тестовых метода

response = requests.post(CREATE_ORDER_URL, data=payload, headers=headers)
body = response.json()

assert response.status_code == 200
assert body["success"] is True
assert len(body["name"]) > 0
assert body["order"]["number"] > 0

@allure.title('Проверка создания заказа с авторизацией, но без ингредиентов')
def test_cant_create_order_without_ingredients(self, user):
payload = {
"ingredients": []
}
response = requests.post(CREATE_ORDER_URL, data=payload, headers={"Authorization": user['accessToken']})
body = response.json()

assert response.status_code == 400
assert body["success"] is False
assert body["message"] == MESSAGE_NO_INGREDIENTS

@allure.title('Проверка создания заказа с неверными ингредиентами')
def test_cant_create_order_without_ingredients(self, user):
payload = {
"ingredients": ["wrong", "ingredient"]
}
response = requests.post(CREATE_ORDER_URL, data=payload, headers={"Authorization": user['accessToken']})

assert response.status_code == 500

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Нужно исправить: проверки лишь статуса кода недостаточно. Необходимо также парсить ответ.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

В данном тесте сервер просто вернет код ответа, тела у него не будет



69 changes: 69 additions & 0 deletions tests/test_create_user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import requests
import allure
from faker import Faker
from urls.urls import CREATE_USER_URL
import pytest


MESSAGE_USER_ALREADY_EXISTS = "User already exists"
MESSAGE_REQUIRED_FIELDS = "Email, password and name are required fields"


class TestCreateUser:

payload = [

@ShamilovR ShamilovR Jan 12, 2025

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Можно лучше: здесь и далее: тестовые данные стоит хранить отдельно в data модуле, так поддерживать и переиспользовать будет проще

{
"email": "test@email.com",
"password": "password"
},
{
"email": "test@email.com",
"name": "John Doe"
},
{
"password": "password",
"name": "John Doe"
}
]

@allure.title('Проверка создания уникального пользователя')
def test_can_create_new_user(self):
fake = Faker("ru_RU")
payload = {
"email": fake.email(),
"password": fake.password(),
"name": fake.name()
}

response = requests.post(CREATE_USER_URL, data=payload)
body = response.json()

assert response.status_code == 200
assert body["success"] is True
assert body["user"]["email"] == payload["email"]
assert body["user"]["name"] == payload["name"]

@allure.title('Проверка наличия ошибки создания пользователя, который уже зарегистрирован')
def test_cant_create_same_user(self, user):
payload = {
"email": user["email"],
"password": user["password"],
"name": user["name"]
}

response = requests.post(CREATE_USER_URL, data=payload)
body = response.json()

assert response.status_code == 403
assert body["success"] is False
assert body["message"] == MESSAGE_USER_ALREADY_EXISTS

@allure.title('Проверка наличия ошибки создания пользователя, у которого не указаны все обязательные поля')
@pytest.mark.parametrize('payload', payload)
def test_cant_create_user_without_any_field(self, payload):
response = requests.post(CREATE_USER_URL, data=payload)
body = response.json()

assert response.status_code == 403
assert body["success"] is False
assert body["message"] == MESSAGE_REQUIRED_FIELDS
37 changes: 37 additions & 0 deletions tests/test_get_user_orders.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import requests
import allure
from urls.urls import USER_ORDER_URL, CREATE_ORDER_URL


MESSAGE_USER_UNAUTHORIZED = "You should be authorised"


class TestGetUserOrders:

@allure.title('Проверка получения заказов пользователя с авторизацией')
def test_can_update_user_data(self, user, random_ingredients):
payload = {
"ingredients": random_ingredients
}
requests.post(CREATE_ORDER_URL, data=payload, headers={"Authorization": user['accessToken']})
response = requests.get(USER_ORDER_URL, headers={"Authorization": user['accessToken']})
body = response.json()

assert response.status_code == 200
assert body["success"] is True
assert body["total"] == 1
assert body["totalToday"] == 1
assert len(body["orders"]) == 1

@allure.title('Проверка получения заказов пользователя без авторизации')
def test_can_update_user_data(self, user, random_ingredients):
payload = {
"ingredients": random_ingredients
}
requests.post(CREATE_ORDER_URL, data=payload, headers={"Authorization": user['accessToken']})
response = requests.get(USER_ORDER_URL)
body = response.json()

assert response.status_code == 401
assert body["success"] is False
assert body["message"] == MESSAGE_USER_UNAUTHORIZED
46 changes: 46 additions & 0 deletions tests/test_update_user_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import requests
import allure
from faker import Faker
from urls.urls import USER_INFO_URL
import pytest


MESSAGE_USER_UNAUTHORIZED = "You should be authorised"


class TestUpdateUserData:

fake = Faker("ru_RU")

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Можно лучше: объект фейкера создается уже не первый раз. По хорошему можно создать хелпер для генерации ланных.


update_data = [
("email", fake.email()),
("name", fake.name()),
("password", fake.password())
]

@allure.title('Проверка изменения данных пользователя с авторизацией')
@pytest.mark.parametrize('update_data', update_data)
def test_can_update_user_data(self, user, update_data):
payload = {
f"{update_data[0]}": update_data[1]
}
response = requests.patch(USER_INFO_URL, data=payload, headers={"Authorization": user['accessToken']})
body = response.json()

assert response.status_code == 200
assert body["success"] is True
if update_data[0] != "password":
assert body["user"][update_data[0]] == update_data[1]

@allure.title('Проверка изменения данных пользователя без авторизации')
@pytest.mark.parametrize('update_data', update_data)
def test_cant_update_user_data(self, user, update_data):
payload = {
f"{update_data[0]}": update_data[1]
}
response = requests.patch(USER_INFO_URL, data=payload)
body = response.json()

assert response.status_code == 401
assert body["success"] is False
assert body["message"] == MESSAGE_USER_UNAUTHORIZED
41 changes: 41 additions & 0 deletions tests/test_user_login.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import requests
import allure
from urls.urls import LOGIN_URL


MESSAGE_INCORRECT_CREDENTIALS = "email or password are incorrect"


class TestUserLogin:

@allure.title('Проверка логина существующего пользователя')
def test_can_login_as_existing_user(self, user):
payload = {
"email": user["email"],
"password": user["password"]
}

response = requests.post(LOGIN_URL, data=payload)
body = response.json()

assert response.status_code == 200
assert body["success"] is True
assert body["user"]["email"] == user["email"]
assert body["user"]["name"] == user["name"]
assert len(body["accessToken"]) > 0
assert len(body["refreshToken"]) > 0

@allure.title('Проверка ошибки логина несуществующего пользователя')
def test_cant_login_as_wrong_user(self, user):
payload = {
"email": user["email"] + "123",
"password": user["password"] + "123"
}

response = requests.post(LOGIN_URL, data=payload)
body = response.json()

assert response.status_code == 401
assert body["success"] is False
assert body["message"] == MESSAGE_INCORRECT_CREDENTIALS

7 changes: 7 additions & 0 deletions urls/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
BASE_URL = "https://stellarburgers.nomoreparties.site"
CREATE_USER_URL = f"{BASE_URL}/api/auth/register"
LOGIN_URL = f"{BASE_URL}/api/auth/login"
USER_INFO_URL = f"{BASE_URL}/api/auth/user"
INGREDIENTS_URL = f"{BASE_URL}/api/ingredients"
CREATE_ORDER_URL = f"{BASE_URL}/api/orders"
USER_ORDER_URL = f"{BASE_URL}/api/orders"