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
55 changes: 55 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Игнорируем виртуальные окружения
.env
.envrc
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Node.js зависимости
node_modules/

# Артефакты сборки
dist/
build/

# Генерируемые файлы
*.pyc
*.log
*.json

# IDE и системные файлы
.idea/
.vscode/
.DS_Store
Thumbs.db

#Прочее
*.txt
__pycache__
.pytest_cache
tests/__pycache__/

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.htmlcov
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py.cover
.hypothesis/
.pytest_cache/
cover/

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
72 changes: 60 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,72 @@
## Задание 1: Юнит-тесты
# Тестирование веб-приложения https://stellarburgers.education-services.ru/ , которая помогает заказать бургер в Stellar Burgers
В данном проекте реализованы автоматизированные тесты с использованием фреймворка pytest.

### Автотесты для проверки программы, которая помогает заказать бургер в Stellar Burgers
---
## Структура проекта
### `praktikum` - пакет, содержащий код программы

### Реализованные сценарии
### Тесты в директории `tests`

Созданы юнит-тесты, покрывающие классы `Bun`, `Burger`, `Ingredient`, `Database`
## Тестируются основные функции класса `Burger`
- Добавление булочек в бургер (`set_buns`)
- Добавление ингрелиентов в бургер (`add_ingredient`)
- Удаление ингредиентов (по индексу) (`remove_ingredient`)
- Перемещение ингредиентов (`move_ingredient`)
- Получение цены бургера (`get_price`)
- Вывод рецепта бургера (`get_receipt`)

Процент покрытия 100% (отчет: `htmlcov/index.html`)
## Описание тестов

### Структура проекта
### 1. `test_set_buns`
Проверяет, что в бургер успешно добавляются булочки.

- `praktikum` - пакет, содержащий код программы
- `tests` - пакет, содержащий тесты, разделенные по классам. Например, `bun_test.py`, `burger_test.py` и т.д.
### 2.1. `test_add_ingredient`
Проверяет, что в бургер успешно добавляются ингредиенты.

### Запуск автотестов
### 2.2. `test_add_multiple_ingredients_param`
Убеждается, что в бургер можно добавить несколько ингредиентов

**Установка зависимостей**
### 3.1 `test_remove_ingredient`
Проверяет, что можно удалить необходимый ингредиент

> `$ pip install -r requirements.txt`
### 3.2. `test_remove_ingredient_invalid_index`
Проверяет, что нельзя удалить недобавленный ингредиент(с несуществующем индексом)

### 3.3. `test_remove_from_empty_burger`
Убеждается, что в пустом бургере (без ингредиентов) нечего удалять

### 4. `test_move_ingredient_param`
Проверяет, что ингредиенты успешно перемещаются внутри бургера

### 5. `test_get_price`
Гарантирует, что цену возможно вывести цену

### 6. `test_get_price_param`
Проверяет, что цену можно получить и с несколькими ингредиентами

### 7. `test_get_receipt`
Проверяет, что получаемый рецепт соответствует эталону

---

## Описание остальных файлов

**conftest.py**
Содержит фикстуры для создания моков

**data.py**
Содержит данные для тестов

---

## Как запустить тесты
pytest -v

## Как установить все зависимости
pip install -r requirements.txt

## Отчет о покрытии
pytest --cov=praktikum --cov-report=html

**Запуск автотестов и создание HTML-отчета о покрытии**

> `$ pytest --cov=praktikum --cov-report=html`
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Empty file added tests/__init__.py
Empty file.
39 changes: 39 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import pytest
from unittest.mock import Mock
from praktikum.burger import Burger


@pytest.fixture
def create_mock_bun():
"""Фикстура возвращает мок булок"""
def _create_mock_bun(name, price):
mock_bun = Mock()
mock_bun.get_name.return_value = name
mock_bun.get_price.return_value = price
return mock_bun
return _create_mock_bun # возвращаем внутреннюю функцию

@pytest.fixture
def create_mock_ingredient():
"""Фикстура возвращает мок ингредиентов"""
def _create_mock_ingredient(type, name, price):
mock_ingredient = Mock()
mock_ingredient.get_type.return_value = type
mock_ingredient.get_name.return_value = name
mock_ingredient.get_price.return_value = price
return mock_ingredient
return _create_mock_ingredient

@pytest.fixture
def create_mock_burger(create_mock_bun, create_mock_ingredient):
"""Фикстура создает бургер"""
def _create_mock_burger(bun_name, ingredients_data):
bun_mock = create_mock_bun(bun_name, 0)
burger = Burger()
burger.set_buns(bun_mock)

for ing_type, ing_name in ingredients_data:
ing_mock = create_mock_ingredient(ing_type, ing_name, 0)
burger.add_ingredient(ing_mock)
return burger
return _create_mock_burger
48 changes: 48 additions & 0 deletions tests/data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from praktikum.ingredient_types import *


class Credentials:
bun_names = ["black bun", "white bun", "red bun", "чёрная булка", "белая булка", "красная булка"]
bun_prices = [100, 200, 300, 101, 99, 109, 201, 299, 301]

ingredient_combination = [
(INGREDIENT_TYPE_SAUCE, "hot sauce", 100),
(INGREDIENT_TYPE_SAUCE, "sour cream", 200),
(INGREDIENT_TYPE_SAUCE, "chili sauce", 300),
(INGREDIENT_TYPE_FILLING, "cutlet", 100),
(INGREDIENT_TYPE_FILLING, "dinosaur", 200),
(INGREDIENT_TYPE_FILLING, "sausage", 300)]

receipt_data = [
("black bun",
[(INGREDIENT_TYPE_SAUCE, "hot sauce")],
300,
"(==== black bun ====)\n= sauce hot sauce =\n(==== black bun ====)\n\nPrice: 300"
),
("white bun",
[(INGREDIENT_TYPE_FILLING, "cutlet")],
400,
"(==== white bun ====)\n= filling cutlet =\n(==== white bun ====)\n\nPrice: 400"
),
("red bun",
[(INGREDIENT_TYPE_SAUCE, "sour cream"), (INGREDIENT_TYPE_FILLING, "dinosaur")],
500,
"(==== red bun ====)\n= sauce sour cream =\n= filling dinosaur =\n(==== red bun ====)\n\nPrice: 500"
),
("black bun",
[
(INGREDIENT_TYPE_SAUCE, "hot sauce"),
(INGREDIENT_TYPE_FILLING, "cutlet"),
(INGREDIENT_TYPE_SAUCE, "chili sauce"),
(INGREDIENT_TYPE_FILLING, "dinosaur")
],
1000,
"(==== black bun ====)\n= sauce hot sauce =\n= filling cutlet =\n= sauce chili sauce =\n= filling dinosaur =\n(==== black bun ====)\n\nPrice: 1000"
),
(
"white bun",
[],
200,
"(==== white bun ====)\n(==== white bun ====)\n\nPrice: 200"
)
]
46 changes: 46 additions & 0 deletions tests/test_add_ingredient.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import pytest
from praktikum.burger import Burger
from praktikum.ingredient_types import INGREDIENT_TYPE_SAUCE, INGREDIENT_TYPE_FILLING
from tests.data import Credentials


class TestAddIngredient:
'''
Проверяется метод добавления ингредиентов
def add_ingredient(self, ingredient: Ingredient):
self.ingredients.append(ingredient)
'''

@pytest.mark.parametrize("ingredient_type, ingredient_name, ingredient_price", Credentials.ingredient_combination)
def test_add_ingredient(self, ingredient_type, ingredient_name, ingredient_price, create_mock_ingredient):

mok_ingredient = create_mock_ingredient(ingredient_type, ingredient_name, ingredient_price)
burger = Burger()
burger.add_ingredient(mok_ingredient)

assert len(burger.ingredients) == 1, "Ингредиент не добавился в бургер"

added_ingredient = burger.ingredients[0] #получить добавленный ингредиент

assert added_ingredient.get_type() == ingredient_type, \
f"Ожидался тип '{ingredient_type}', получен '{added_ingredient.get_type()}'"
assert added_ingredient.get_name() == ingredient_name, \
f"Ожидалось имя '{ingredient_name}', получено '{added_ingredient.get_name()}'"
assert added_ingredient.get_price() == ingredient_price, \
f"Ожидалась цена {ingredient_price}, получена {added_ingredient.get_price()}"

#Проверяем, что можно добавить разное количество ингредиентов
@pytest.mark.parametrize("ingredients_count", [1, 2, 3, 4, 5])
def test_add_multiple_ingredients_param(self, ingredients_count, create_mock_ingredient):
burger = Burger()

for i in range(ingredients_count):
mock_ingredient = create_mock_ingredient(
INGREDIENT_TYPE_SAUCE,
f"sauce_{i}",
i * 100
)
burger.add_ingredient(mock_ingredient)

assert len(burger.ingredients) == ingredients_count, \
f"Ожидалось {ingredients_count} ингредиентов, получено {len(burger.ingredients)}"
59 changes: 59 additions & 0 deletions tests/test_get_price.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
from unittest.mock import Mock
import pytest
from praktikum.burger import Burger


class TestGetPrice:

'''Проверяется метод получения цены на бургер
def get_price(self) -> float:
price = self.bun.get_price() * 2

for ingredient in self.ingredients:
price += ingredient.get_price()

return price
'''

@pytest.mark.parametrize("bun_price, ingredient_price, expected_price", [
(100, 100, 300),
(200, 200, 600),
(300, 300, 900)
])

def test_get_price(self, bun_price, ingredient_price, expected_price):
mock_bun = Mock()
mock_bun.get_price.return_value = bun_price
mock_ingredient = Mock()
mock_ingredient.get_price.return_value = ingredient_price

burger = Burger()
burger.set_buns(mock_bun)
burger.add_ingredient(mock_ingredient)
price = burger.get_price()

assert price == expected_price, \
f"Ожидалась цена {expected_price}, но получена {price}"

#несколько ингредиентов
@pytest.mark.parametrize("bun_price, ingredient_price, expected_price", [
(100, [100, 100], 400),
(200, [200, 100], 700),
(300, [300, 200, 100], 1200)
])
def test_get_price_param(self, bun_price, ingredient_price, expected_price):
mock_bun = Mock()
mock_bun.get_price.return_value = bun_price

burger = Burger()
burger.set_buns(mock_bun)

for ing_price in ingredient_price:
mock_ingredient = Mock()
mock_ingredient.get_price.return_value = ing_price
burger.add_ingredient(mock_ingredient)

price = burger.get_price()

assert price == expected_price, \
f"Ожидалась цена {expected_price}, но получена {price}"
31 changes: 31 additions & 0 deletions tests/test_get_receipt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from unittest.mock import patch
import pytest
from tests.data import Credentials
from praktikum.burger import Burger


class TestGetReceipt:

'''Проверяется метод получения рецепта на бургер
def get_receipt(self) -> str:
receipt: List[str] = [f'(==== {self.bun.get_name()} ====)']

for ingredient in self.ingredients:
receipt.append(f'= {str(ingredient.get_type()).lower()} {ingredient.get_name()} =')

receipt.append(f'(==== {self.bun.get_name()} ====)\n')
receipt.append(f'Price: {self.get_price()}')

return '\n'.join(receipt)
'''

@pytest.mark.parametrize("bun_name, ingredients_data, mock_price, expected_receipt", Credentials.receipt_data)
@patch('praktikum.burger.Burger.get_price')
def test_get_receipt(self, mock_get_price, bun_name, ingredients_data, mock_price, expected_receipt, create_mock_burger):

burger = create_mock_burger(bun_name, ingredients_data)
mock_get_price.return_value = mock_price
receipt = burger.get_receipt()

assert receipt == expected_receipt

Loading