From af61f6c3f12386a5e5fccd5eb0c09343873ab712 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=95=D0=B2=D0=B3=D0=B5=D0=BD=D0=B8=D0=B9?= Date: Fri, 4 Sep 2026 18:59:49 +0500 Subject: [PATCH] done --- .gitignore | 8 ++ README.md | 2 +- __init__.py => praktikum/__init__.py | 0 bun.py => praktikum/bun.py | 0 burger.py => praktikum/burger.py | 0 database.py => praktikum/database.py | 0 ingredient.py => praktikum/ingredient.py | 0 .../ingredient_types.py | 0 pytest.ini | 2 + requirements.txt | 2 + tests/__init__.py | 0 tests/conftest.py | 39 ++++++++ tests/data.py | 38 ++++++++ tests/test_bun.py | 18 ++++ tests/test_burger.py | 92 +++++++++++++++++++ tests/test_database.py | 25 +++++ tests/test_ingredient.py | 24 +++++ 17 files changed, 249 insertions(+), 1 deletion(-) create mode 100644 .gitignore rename __init__.py => praktikum/__init__.py (100%) rename bun.py => praktikum/bun.py (100%) rename burger.py => praktikum/burger.py (100%) rename database.py => praktikum/database.py (100%) rename ingredient.py => praktikum/ingredient.py (100%) rename ingredient_types.py => praktikum/ingredient_types.py (100%) create mode 100644 pytest.ini create mode 100644 requirements.txt create mode 100644 tests/__init__.py create mode 100644 tests/conftest.py create mode 100644 tests/data.py create mode 100644 tests/test_bun.py create mode 100644 tests/test_burger.py create mode 100644 tests/test_database.py create mode 100644 tests/test_ingredient.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..0eba4b3da --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +__pycache__/ +*.pyc +.pytest_cache/ +.coverage +htmlcov/ +*.egg-info/ +.venv/ +venv/ diff --git a/README.md b/README.md index 272081708..808865fe4 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ ### Структура проекта - `praktikum` - пакет, содержащий код программы -- `tests` - пакет, содержащий тесты, разделенные по классам. Например, `bun_test.py`, `burger_test.py` и т.д. +- `tests` - пакет, содержащий тесты, разделенные по классам. Например, `test_bun.py`, `test_burger.py` и т.д. ### Запуск автотестов diff --git a/__init__.py b/praktikum/__init__.py similarity index 100% rename from __init__.py rename to praktikum/__init__.py diff --git a/bun.py b/praktikum/bun.py similarity index 100% rename from bun.py rename to praktikum/bun.py diff --git a/burger.py b/praktikum/burger.py similarity index 100% rename from burger.py rename to praktikum/burger.py diff --git a/database.py b/praktikum/database.py similarity index 100% rename from database.py rename to praktikum/database.py diff --git a/ingredient.py b/praktikum/ingredient.py similarity index 100% rename from ingredient.py rename to praktikum/ingredient.py diff --git a/ingredient_types.py b/praktikum/ingredient_types.py similarity index 100% rename from ingredient_types.py rename to praktikum/ingredient_types.py diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 000000000..5ee647716 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +testpaths = tests diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..47605955f --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +pytest==8.3.4 +pytest-cov==7.1.0 diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 000000000..fe5542495 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,39 @@ +from unittest.mock import Mock + +import pytest + +from praktikum.bun import Bun +from praktikum.burger import Burger +from praktikum.database import Database +from praktikum.ingredient import Ingredient +from tests.data import BURGER_BUN, BURGER_INGREDIENTS + + +@pytest.fixture +def burger(): + return Burger() + + +@pytest.fixture +def bun_mock(): + bun = Mock(spec=Bun) + bun.get_name.return_value = BURGER_BUN[0] + bun.get_price.return_value = BURGER_BUN[1] + return bun + + +@pytest.fixture +def ingredient_mocks(): + mocks = [] + for ingredient_type, name, price in BURGER_INGREDIENTS: + ingredient = Mock(spec=Ingredient) + ingredient.get_type.return_value = ingredient_type + ingredient.get_name.return_value = name + ingredient.get_price.return_value = price + mocks.append(ingredient) + return mocks + + +@pytest.fixture +def database(): + return Database() diff --git a/tests/data.py b/tests/data.py new file mode 100644 index 000000000..a7d70a62a --- /dev/null +++ b/tests/data.py @@ -0,0 +1,38 @@ +from praktikum.ingredient_types import INGREDIENT_TYPE_FILLING, INGREDIENT_TYPE_SAUCE + +BUN_CASES = ( + ("classic bun", 100), + ("premium bun", 200.5), +) + +INGREDIENT_CASES = ( + (INGREDIENT_TYPE_SAUCE, "spicy sauce", 50), + (INGREDIENT_TYPE_FILLING, "beef patty", 150), +) + +BURGER_BUN = ("test bun", 100) + +BURGER_INGREDIENTS = ( + (INGREDIENT_TYPE_SAUCE, "hot sauce", 30), + (INGREDIENT_TYPE_FILLING, "cutlet", 120), + (INGREDIENT_TYPE_SAUCE, "mayo", 25), +) + +REMOVE_INGREDIENT_CASES = ( + (0, (1, 2)), + (1, (0, 2)), + (2, (0, 1)), + (-1, (0, 1)), +) + +MOVE_INGREDIENT_CASES = ( + (0, 2, (1, 2, 0)), + (2, 0, (2, 0, 1)), + (1, 1, (0, 1, 2)), +) + +DATABASE_BUN_NAMES = ("black bun", "white bun", "red bun") +DATABASE_BUN_PRICES = (100, 200, 300) +DATABASE_INGREDIENT_COUNT = 6 +DATABASE_SAUCE_COUNT = 3 +DATABASE_FILLING_COUNT = 3 diff --git a/tests/test_bun.py b/tests/test_bun.py new file mode 100644 index 000000000..6ed056276 --- /dev/null +++ b/tests/test_bun.py @@ -0,0 +1,18 @@ +import pytest + +from praktikum.bun import Bun +from tests.data import BUN_CASES + + +class TestBun: + @pytest.mark.parametrize("name, price", BUN_CASES) + def test_get_name_returns_given_name(self, name, price): + bun = Bun(name, price) + + assert bun.get_name() == name + + @pytest.mark.parametrize("name, price", BUN_CASES) + def test_get_price_returns_given_price(self, name, price): + bun = Bun(name, price) + + assert bun.get_price() == price diff --git a/tests/test_burger.py b/tests/test_burger.py new file mode 100644 index 000000000..69c4c9571 --- /dev/null +++ b/tests/test_burger.py @@ -0,0 +1,92 @@ +import pytest + +from tests.data import ( + BURGER_BUN, + BURGER_INGREDIENTS, + MOVE_INGREDIENT_CASES, + REMOVE_INGREDIENT_CASES, +) + + +class TestBurger: + def test_get_price_without_ingredients_returns_double_bun_price(self, burger, bun_mock): + burger.set_buns(bun_mock) + + assert burger.get_price() == BURGER_BUN[1] * 2 + bun_mock.get_price.assert_called_once_with() + + def test_add_ingredient_includes_ingredient_in_price(self, burger, bun_mock, ingredient_mocks): + burger.set_buns(bun_mock) + burger.add_ingredient(ingredient_mocks[0]) + + expected_price = BURGER_BUN[1] * 2 + BURGER_INGREDIENTS[0][2] + assert burger.get_price() == expected_price + assert burger.ingredients == [ingredient_mocks[0]] + + def test_get_price_with_several_ingredients_returns_total(self, burger, bun_mock, ingredient_mocks): + burger.set_buns(bun_mock) + for ingredient in ingredient_mocks: + burger.add_ingredient(ingredient) + + expected_price = BURGER_BUN[1] * 2 + sum(item[2] for item in BURGER_INGREDIENTS) + assert burger.get_price() == expected_price + + @pytest.mark.parametrize("index, remaining_indices", REMOVE_INGREDIENT_CASES) + def test_remove_ingredient_excludes_item_from_price( + self, burger, bun_mock, ingredient_mocks, index, remaining_indices + ): + burger.set_buns(bun_mock) + for ingredient in ingredient_mocks: + burger.add_ingredient(ingredient) + + burger.remove_ingredient(index) + + expected_price = BURGER_BUN[1] * 2 + sum( + BURGER_INGREDIENTS[item_index][2] for item_index in remaining_indices + ) + assert burger.get_price() == expected_price + assert burger.ingredients == [ingredient_mocks[item_index] for item_index in remaining_indices] + + @pytest.mark.parametrize("index, new_index, expected_order", MOVE_INGREDIENT_CASES) + def test_move_ingredient_changes_order( + self, burger, bun_mock, ingredient_mocks, index, new_index, expected_order + ): + burger.set_buns(bun_mock) + for ingredient in ingredient_mocks: + burger.add_ingredient(ingredient) + + burger.move_ingredient(index, new_index) + + assert burger.ingredients == [ingredient_mocks[item_index] for item_index in expected_order] + + def test_get_receipt_without_ingredients_returns_bun_only(self, burger, bun_mock): + burger.set_buns(bun_mock) + + receipt = burger.get_receipt() + + expected_receipt = "\n".join( + [ + f"(==== {BURGER_BUN[0]} ====)", + f"(==== {BURGER_BUN[0]} ====)\n", + f"Price: {burger.get_price()}", + ] + ) + assert receipt == expected_receipt + + def test_get_receipt_returns_formatted_receipt(self, burger, bun_mock, ingredient_mocks): + burger.set_buns(bun_mock) + for ingredient in ingredient_mocks[:2]: + burger.add_ingredient(ingredient) + + receipt = burger.get_receipt() + + expected_receipt = "\n".join( + [ + f"(==== {BURGER_BUN[0]} ====)", + f"= {BURGER_INGREDIENTS[0][0].lower()} {BURGER_INGREDIENTS[0][1]} =", + f"= {BURGER_INGREDIENTS[1][0].lower()} {BURGER_INGREDIENTS[1][1]} =", + f"(==== {BURGER_BUN[0]} ====)\n", + f"Price: {burger.get_price()}", + ] + ) + assert receipt == expected_receipt diff --git a/tests/test_database.py b/tests/test_database.py new file mode 100644 index 000000000..26f649b9c --- /dev/null +++ b/tests/test_database.py @@ -0,0 +1,25 @@ +from praktikum.ingredient_types import INGREDIENT_TYPE_FILLING, INGREDIENT_TYPE_SAUCE +from tests.data import ( + DATABASE_BUN_NAMES, + DATABASE_BUN_PRICES, + DATABASE_FILLING_COUNT, + DATABASE_INGREDIENT_COUNT, + DATABASE_SAUCE_COUNT, +) + + +class TestDatabase: + def test_available_buns_returns_all_buns(self, database): + buns = database.available_buns() + + assert len(buns) == len(DATABASE_BUN_NAMES) + assert tuple(bun.get_name() for bun in buns) == DATABASE_BUN_NAMES + assert tuple(bun.get_price() for bun in buns) == DATABASE_BUN_PRICES + + def test_available_ingredients_returns_sauces_and_fillings(self, database): + ingredients = database.available_ingredients() + types = [ingredient.get_type() for ingredient in ingredients] + + assert len(ingredients) == DATABASE_INGREDIENT_COUNT + assert types.count(INGREDIENT_TYPE_SAUCE) == DATABASE_SAUCE_COUNT + assert types.count(INGREDIENT_TYPE_FILLING) == DATABASE_FILLING_COUNT diff --git a/tests/test_ingredient.py b/tests/test_ingredient.py new file mode 100644 index 000000000..4a32820a2 --- /dev/null +++ b/tests/test_ingredient.py @@ -0,0 +1,24 @@ +import pytest + +from praktikum.ingredient import Ingredient +from tests.data import INGREDIENT_CASES + + +class TestIngredient: + @pytest.mark.parametrize("ingredient_type, name, price", INGREDIENT_CASES) + def test_get_type_returns_given_type(self, ingredient_type, name, price): + ingredient = Ingredient(ingredient_type, name, price) + + assert ingredient.get_type() == ingredient_type + + @pytest.mark.parametrize("ingredient_type, name, price", INGREDIENT_CASES) + def test_get_name_returns_given_name(self, ingredient_type, name, price): + ingredient = Ingredient(ingredient_type, name, price) + + assert ingredient.get_name() == name + + @pytest.mark.parametrize("ingredient_type, name, price", INGREDIENT_CASES) + def test_get_price_returns_given_price(self, ingredient_type, name, price): + ingredient = Ingredient(ingredient_type, name, price) + + assert ingredient.get_price() == price