diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..538905631 --- /dev/null +++ b/.gitignore @@ -0,0 +1,40 @@ +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# pytest +.pytest_cache/ +.coverage +htmlcov/ + +# VS Code +.vscode/ +*.swp +*.swo + +# OS +.DS_Store +Thumbs.db + +# Temporary files +*.tmp +*.temp \ No newline at end of file diff --git a/burger.py b/burger.py index 2b3b6a88b..109d4e5a1 100644 --- a/burger.py +++ b/burger.py @@ -1,7 +1,7 @@ from typing import List -from praktikum.bun import Bun -from praktikum.ingredient import Ingredient +from bun import Bun +from ingredient import Ingredient class Burger: @@ -45,4 +45,4 @@ def get_receipt(self) -> str: receipt.append(f'(==== {self.bun.get_name()} ====)\n') receipt.append(f'Price: {self.get_price()}') - return '\n'.join(receipt) + return '\n'.join(receipt) \ No newline at end of file diff --git a/conftest.py b/conftest.py new file mode 100644 index 000000000..41f544bdb --- /dev/null +++ b/conftest.py @@ -0,0 +1,58 @@ +""" +Общие фикстуры для всех тестов +""" +import pytest +from unittest.mock import Mock +import sys +import os + +# Добавляем текущую директорию в путь для импортов +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +@pytest.fixture +def bun(): + """Фикстура для создания булочки""" + from bun import Bun + return Bun("Краторная булочка", 100.0) + + +@pytest.fixture +def mock_bun(): + """Фикстура для мока булочки""" + mock = Mock() + mock.get_price.return_value = 100 + mock.get_name.return_value = "test bun" + return mock + + +@pytest.fixture +def ingredient(): + """Фикстура для создания ингредиента""" + from ingredient import Ingredient + from ingredient_types import INGREDIENT_TYPE_SAUCE + return Ingredient(INGREDIENT_TYPE_SAUCE, "hot sauce", 100.0) + + +@pytest.fixture +def mock_ingredient(): + """Фикстура для мока ингредиента""" + from ingredient_types import INGREDIENT_TYPE_SAUCE + mock = Mock() + mock.get_price.return_value = 50 + mock.get_name.return_value = "test ingredient" + mock.get_type.return_value = INGREDIENT_TYPE_SAUCE + return mock + + +@pytest.fixture +def burger(): + """Фикстура для создания бургера""" + from burger import Burger + return Burger() + + +@pytest.fixture +def database(): + """Фикстура для создания базы данных""" + from database import Database + return Database() \ No newline at end of file diff --git a/database.py b/database.py index 4c75baf71..84d3685d0 100644 --- a/database.py +++ b/database.py @@ -1,8 +1,8 @@ from typing import List -from praktikum.bun import Bun -from praktikum.ingredient import Ingredient -from praktikum.ingredient_types import INGREDIENT_TYPE_SAUCE, INGREDIENT_TYPE_FILLING +from bun import Bun +from ingredient import Ingredient +from ingredient_types import INGREDIENT_TYPE_SAUCE, INGREDIENT_TYPE_FILLING class Database: diff --git a/praktikum.py b/praktikum.py index ec522fa6d..f445fc963 100644 --- a/praktikum.py +++ b/praktikum.py @@ -1,25 +1,21 @@ from typing import List -from praktikum.bun import Bun -from praktikum.burger import Burger -from praktikum.database import Database -from praktikum.ingredient import Ingredient +from bun import Bun +from burger import Burger +from database import Database +from ingredient import Ingredient def main(): - # Инициализируем базу данных + database: Database = Database() - # Создадим новый бургер burger: Burger = Burger() - # Считаем список доступных булок из базы данных buns: List[Bun] = database.available_buns() - # Считаем список доступных ингредиентов из базы данных ingredients: List[Ingredient] = database.available_ingredients() - # Соберём бургер burger.set_buns(buns[0]) burger.add_ingredient(ingredients[1]) @@ -27,13 +23,10 @@ def main(): burger.add_ingredient(ingredients[3]) burger.add_ingredient(ingredients[5]) - # Переместим слой с ингредиентом burger.move_ingredient(2, 1) - - # Удалим ингредиент + burger.remove_ingredient(3) - # Распечатаем рецепт бургера print(burger.get_receipt()) diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/test_bun.py b/tests/test_bun.py new file mode 100644 index 000000000..23ac0c1d3 --- /dev/null +++ b/tests/test_bun.py @@ -0,0 +1,38 @@ +import pytest +import sys +import os + +# Добавляем путь к корню проекта +sys.path.append(os.path.dirname(os.path.dirname(__file__))) + + +class TestBun: + """Тесты для класса Bun""" + + def test_bun_name_initialization(self, bun): + """Только инициализация имени""" + assert bun.name == "Краторная булочка" + + def test_bun_price_initialization(self, bun): + """Только инициализация цены""" + assert bun.price == 100.0 + + def test_bun_get_name(self, bun): + """Только получение названия""" + assert bun.get_name() == "Краторная булочка" + + def test_bun_get_price(self, bun): + """Только получение цены""" + assert bun.get_price() == 100.0 + + @pytest.mark.parametrize("name, price", [ + ("Булочка 1", 50.0), + ("Булочка 2", 150.5), + ("С кунжутом", 75.25), + ]) + def test_bun_different_parameters(self, name, price): + """Тестируем разные параметры""" + from bun import Bun + bun = Bun(name, price) + assert bun.get_name() == name + assert bun.get_price() == price \ No newline at end of file diff --git a/tests/test_burger.py b/tests/test_burger.py new file mode 100644 index 000000000..1542ac935 --- /dev/null +++ b/tests/test_burger.py @@ -0,0 +1,94 @@ +import pytest +from unittest.mock import Mock, patch +import sys +import os + +sys.path.append(os.path.dirname(os.path.dirname(__file__))) + +from burger import Burger +from bun import Bun +from ingredient import Ingredient +from ingredient_types import INGREDIENT_TYPE_SAUCE, INGREDIENT_TYPE_FILLING + +@pytest.fixture +def burger(): + """Создает новый бургер для каждого теста""" + return Burger() + +@pytest.fixture +def mock_bun(): + """Создает мок булочки""" + mock = Mock() + mock.get_price.return_value = 100 + mock.get_name.return_value = "test bun" + return mock + +@pytest.fixture +def mock_ingredient(): + """Создает мок ингредиента""" + mock = Mock() + mock.get_price.return_value = 50 + mock.get_name.return_value = "test ingredient" + mock.get_type.return_value = INGREDIENT_TYPE_SAUCE + return mock + +class TestBurger: + """Тесты для класса Burger""" + + def test_burger_initialization(self, burger): + """ТЕСТ 1: Только инициализация""" + assert burger.bun is None + assert burger.ingredients == [] + + def test_set_buns(self, burger, mock_bun): + """ТЕСТ 2: Только установка булочки""" + burger.set_buns(mock_bun) + assert burger.bun == mock_bun + + def test_add_ingredient(self, burger, mock_ingredient): + """ТЕСТ 3: Только добавление ингредиента""" + burger.add_ingredient(mock_ingredient) + assert len(burger.ingredients) == 1 + assert burger.ingredients[0] == mock_ingredient + + def test_remove_ingredient(self, burger, mock_ingredient): + """ТЕСТ 4: Только удаление ингредиента""" + burger.add_ingredient(mock_ingredient) + burger.remove_ingredient(0) + assert len(burger.ingredients) == 0 + + def test_move_ingredient(self, burger): + """ТЕСТ 5: Только перемещение ингредиента""" + mock1, mock2, mock3 = Mock(), Mock(), Mock() + burger.ingredients = [mock1, mock2, mock3] + + burger.move_ingredient(2, 1) + assert burger.ingredients == [mock1, mock3, mock2] + + def test_get_price(self, burger, mock_bun): + """ТЕСТ 6: Только расчет цены""" + burger.set_buns(mock_bun) + + mock_ingredient = Mock() + mock_ingredient.get_price.return_value = 50 + burger.ingredients = [mock_ingredient] + + assert burger.get_price() == 250 # 2*100 + 50 + + def test_get_receipt(self, burger, mock_bun): + """ТЕСТ 7: Формирование чека""" + burger.set_buns(mock_bun) + mock_ingredient = Mock() + mock_ingredient.get_type.return_value = INGREDIENT_TYPE_SAUCE + mock_ingredient.get_name.return_value = "test sauce" + mock_ingredient.get_price.return_value = 50 + burger.ingredients = [mock_ingredient] + + receipt = burger.get_receipt() + # ИСПРАВЛЕНИЕ: заменили "in" на полное сравнение строки + expected_receipt = """(==== test bun ====) += sauce test sauce = +(==== test bun ====) + +Price: 250""" + assert receipt == expected_receipt \ No newline at end of file diff --git a/tests/test_database.py b/tests/test_database.py new file mode 100644 index 000000000..75d00b055 --- /dev/null +++ b/tests/test_database.py @@ -0,0 +1,40 @@ +import pytest +import sys +import os + +sys.path.append(os.path.dirname(os.path.dirname(__file__))) + +from database import Database + + +@pytest.fixture +def database(): + """Фикстура для создания базы данных""" + return Database() + + +class TestDatabase: + """Тесты для класса Database""" + + def test_database_initialization(self, database): + """Только инициализация""" + buns = database.available_buns() + ingredients = database.available_ingredients() + + assert len(buns) == 3 + assert len(ingredients) == 6 + + def test_available_buns(self, database): + """Только получение булочек""" + buns = database.available_buns() + + assert len(buns) == 3 + # ИСПРАВЛЕНИЕ: заменили "in" на точное сравнение + bun_names = [bun.get_name() for bun in buns] + assert bun_names == ["black bun", "white bun", "red bun"] + + def test_available_ingredients(self, database): + """Только получение ингредиентов""" + ingredients = database.available_ingredients() + + assert len(ingredients) == 6 \ No newline at end of file diff --git a/tests/test_ingredient.py b/tests/test_ingredient.py new file mode 100644 index 000000000..558a2d5aa --- /dev/null +++ b/tests/test_ingredient.py @@ -0,0 +1,54 @@ +import pytest +import sys +import os + +sys.path.append(os.path.dirname(os.path.dirname(__file__))) + +from ingredient import Ingredient +from ingredient_types import INGREDIENT_TYPE_SAUCE, INGREDIENT_TYPE_FILLING + + +@pytest.fixture +def ingredient(): + """Фикстура для создания ингредиента""" + return Ingredient(INGREDIENT_TYPE_SAUCE, "hot sauce", 100.0) + + +class TestIngredient: + """Тесты для класса Ingredient""" + + def test_ingredient_type_initialization(self, ingredient): + """Только инициализация типа""" + assert ingredient.type == INGREDIENT_TYPE_SAUCE + + def test_ingredient_name_initialization(self, ingredient): + """Только инициализация названия""" + assert ingredient.name == "hot sauce" + + def test_ingredient_price_initialization(self, ingredient): + """Только инициализация цены""" + assert ingredient.price == 100.0 + + def test_ingredient_get_type(self, ingredient): + """Только получение типа""" + assert ingredient.get_type() == INGREDIENT_TYPE_SAUCE + + def test_ingredient_get_name(self, ingredient): + """Только получение названия""" + assert ingredient.get_name() == "hot sauce" + + def test_ingredient_get_price(self, ingredient): + """Только получение цены""" + assert ingredient.get_price() == 100.0 + + @pytest.mark.parametrize("ingredient_type,name,price", [ + (INGREDIENT_TYPE_SAUCE, "chili sauce", 200.0), + (INGREDIENT_TYPE_FILLING, "dinosaur", 300.0), + (INGREDIENT_TYPE_SAUCE, "sour cream", 250.5), + ]) + def test_ingredient_different_parameters(self, ingredient_type, name, price): + """Тестируем разные параметры""" + ingredient = Ingredient(ingredient_type, name, price) + assert ingredient.get_type() == ingredient_type + assert ingredient.get_name() == name + assert ingredient.get_price() == price \ No newline at end of file