From f71b08fa85cf755f454454ddfe0632947e40ae8a Mon Sep 17 00:00:00 2001 From: Antivilod Date: Wed, 11 Mar 2026 08:34:33 +0300 Subject: [PATCH] Add my solution for Task 1 --- .coverage | Bin 0 -> 53248 bytes praktikum/README.md | 24 ++++++++ praktikum/__init__.py | 0 praktikum/bun.py | 15 +++++ praktikum/burger.py | 48 +++++++++++++++ praktikum/database.py | 33 ++++++++++ praktikum/ingredient.py | 20 +++++++ praktikum/ingredient_types.py | 7 +++ praktikum/praktikum.py | 41 +++++++++++++ requirements.txt | 0 tests/__init__.py | 0 tests/data/__init__.py | 0 tests/data/test_data.py | 28 +++++++++ tests/test_bun.py | 28 +++++++++ tests/test_burger.py | 109 ++++++++++++++++++++++++++++++++++ tests/test_database.py | 25 ++++++++ tests/test_ingredient.py | 53 +++++++++++++++++ 17 files changed, 431 insertions(+) create mode 100644 .coverage create mode 100644 praktikum/README.md create mode 100644 praktikum/__init__.py create mode 100644 praktikum/bun.py create mode 100644 praktikum/burger.py create mode 100644 praktikum/database.py create mode 100644 praktikum/ingredient.py create mode 100644 praktikum/ingredient_types.py create mode 100644 praktikum/praktikum.py create mode 100644 requirements.txt create mode 100644 tests/__init__.py create mode 100644 tests/data/__init__.py create mode 100644 tests/data/test_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/.coverage b/.coverage new file mode 100644 index 0000000000000000000000000000000000000000..045e92c0b5b5ef3a16d80165e55242f23d8441bc GIT binary patch literal 53248 zcmeI)&2QUe90zbacI+li;=&kFS519DLS41ABiaENn^@abVho85HpHRAbCM^mX<}!# zv$Y4PGA4%j6A*s^h$|yzU9V{c?5H#$$+C2kF-ej#^vKgAnRJ>_lLdN}`{swuW~BK~p2{0< zOF8Ww$#^$^z?jRe=KdJ}EcasO!nm!MGV`;^<@^VV~4Vgrnxz`z&!T~YjKa&?FMJIQ?sj9U^}ZUSmVjw zZJ*b~F^ksGQA_MNAEp;`rd^{{0bivMEzfRR-X>e;o277v_}v1&5kxB}2)9=qu?IU8 zC!b{=uXB$(RqjW*IAqsmv$G#=W%c5|ee!i4mdWy}^fx|G8d}jS%IP`QfY){`U`e1Q6XErjhGJb5 z1-clejNhwIr_!DDu+@;ZydP8QVvTS zxN%|cyKZ)<%U*d0sxu)MH5#RAJNBhE?^b?^^-`9?VmNMzi9%2dcy3%PzO+x4s8#X} z|5AfKI+<2GaKmMjD&H*AQ|{UmV|sCVTE2cMY$$@qtk{9yoyiO|n(pc$O-F1W-fl!M z8Ehn?7d0Bpt%qGkq-Ig&P;2h*Ge;5(%M%@qx$%ya(}&vHL}n=utkQ5RgKaHrF+Qgb zLSsR)TfOa6MOX1f8LIAO?pdpRKHeG)3lF;?QPU}BwBqvgu%^>(0%o~8o9#?$dU0w> zzM2V}QCwT`i$2hVlA7FM7)>@cx#hRLWFWcMAep4-jgm=^j z#j|#8A{A!&V9mSua?WoZnKjsQ&TShHwntKznU zu>Fd~uz8AOPcOewfZlRqPkYUVyHoc*>-xS;hgEUd@{c8J+02^di&4m*VHMYHaLb8~ z4V2=vPw#2_EX>2*N2OPKG5k#tWA*Y(n5X36B8K_%)ajD`MKjH&<<#Qil{gGXQEBWK zom0F|G>A|_Hbb4#r!KlJW)d{sDn_g%{(Or}MAW8Li@Lk0l)i{p*7#lFqNC9%E8v0M zH?v?UosqteXIDEDeRqKeJ3cot{LW8$M+ zXIj>ahY!o0cHD!b!O8ULlR(o-${H`G23pp(jlD+p294765vjj%3GhBcu^7FB7!jjt zuS9goUhxN{?5sG!myJ6T{b7Ot1Rwwb2tWV=5P$##AOHafKw$R?C~`{H#rc2A_(?Ku z(-S5LKmY;|fB*y_009U<00Izz00bUOfm}*CXe9p@^8AFXOijlB1MtFp`RIH(OQlK~ zwvrK(S?PNv?(s%x^ol!fJqr}+Z{6D>{cJdDvi%O*~sGamEQM%{< z$_Zs_v;gA#Keb4zqg++#JO9V;|LwUBjRHde0uX=z1Rwwb2tWV=5P-nm5>RAC%8UE| zvhklpf0!Tu0SG_<0uX=z1Rwwb2tWV=5ZHwRijvQW`~RBpon-uL{BHbg{9t@f3z#4P z0SG_<0uX=z1Rwwb2tWV=5P0MSG)B@L@^)$0SG_<0uX=z1Rwwb2tWV=Lj=V4|8f351P7}j Y009U<00Izz00bZa0SG_<0=q=ue=e1^Qvd(} literal 0 HcmV?d00001 diff --git a/praktikum/README.md b/praktikum/README.md new file mode 100644 index 000000000..272081708 --- /dev/null +++ b/praktikum/README.md @@ -0,0 +1,24 @@ +## Задание 1: Юнит-тесты + +### Автотесты для проверки программы, которая помогает заказать бургер в Stellar Burgers + +### Реализованные сценарии + +Созданы юнит-тесты, покрывающие классы `Bun`, `Burger`, `Ingredient`, `Database` + +Процент покрытия 100% (отчет: `htmlcov/index.html`) + +### Структура проекта + +- `praktikum` - пакет, содержащий код программы +- `tests` - пакет, содержащий тесты, разделенные по классам. Например, `bun_test.py`, `burger_test.py` и т.д. + +### Запуск автотестов + +**Установка зависимостей** + +> `$ pip install -r requirements.txt` + +**Запуск автотестов и создание HTML-отчета о покрытии** + +> `$ pytest --cov=praktikum --cov-report=html` diff --git a/praktikum/__init__.py b/praktikum/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/praktikum/bun.py b/praktikum/bun.py new file mode 100644 index 000000000..5504bc1f4 --- /dev/null +++ b/praktikum/bun.py @@ -0,0 +1,15 @@ +class Bun: + """ + Модель булочки для бургера. + Булочке можно дать название и назначить цену. + """ + + def __init__(self, name: str, price: float): + self.name = name + self.price = price + + def get_name(self) -> str: + return self.name + + def get_price(self) -> float: + return self.price diff --git a/praktikum/burger.py b/praktikum/burger.py new file mode 100644 index 000000000..2b3b6a88b --- /dev/null +++ b/praktikum/burger.py @@ -0,0 +1,48 @@ +from typing import List + +from praktikum.bun import Bun +from praktikum.ingredient import Ingredient + + +class Burger: + """ + Модель бургера. + Бургер состоит из булочек и ингредиентов (начинка или соус). + Ингредиенты можно перемещать и удалять. + Можно распечать чек с информацией о бургере. + """ + + def __init__(self): + self.bun = None + self.ingredients: List[Ingredient] = [] + + def set_buns(self, bun: Bun): + self.bun = bun + + def add_ingredient(self, ingredient: Ingredient): + self.ingredients.append(ingredient) + + def remove_ingredient(self, index: int): + del self.ingredients[index] + + def move_ingredient(self, index: int, new_index: int): + self.ingredients.insert(new_index, self.ingredients.pop(index)) + + def get_price(self) -> float: + price = self.bun.get_price() * 2 + + for ingredient in self.ingredients: + price += ingredient.get_price() + + return price + + 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) diff --git a/praktikum/database.py b/praktikum/database.py new file mode 100644 index 000000000..4c75baf71 --- /dev/null +++ b/praktikum/database.py @@ -0,0 +1,33 @@ +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 + + +class Database: + """ + Класс с методами по работе с базой данных. + """ + + def __init__(self): + self.buns: List[Bun] = [] + self.ingredients: List[Ingredient] = [] + + self.buns.append(Bun("black bun", 100)) + self.buns.append(Bun("white bun", 200)) + self.buns.append(Bun("red bun", 300)) + + self.ingredients.append(Ingredient(INGREDIENT_TYPE_SAUCE, "hot sauce", 100)) + self.ingredients.append(Ingredient(INGREDIENT_TYPE_SAUCE, "sour cream", 200)) + self.ingredients.append(Ingredient(INGREDIENT_TYPE_SAUCE, "chili sauce", 300)) + + self.ingredients.append(Ingredient(INGREDIENT_TYPE_FILLING, "cutlet", 100)) + self.ingredients.append(Ingredient(INGREDIENT_TYPE_FILLING, "dinosaur", 200)) + self.ingredients.append(Ingredient(INGREDIENT_TYPE_FILLING, "sausage", 300)) + + def available_buns(self) -> List[Bun]: + return self.buns + + def available_ingredients(self) -> List[Ingredient]: + return self.ingredients diff --git a/praktikum/ingredient.py b/praktikum/ingredient.py new file mode 100644 index 000000000..0e50db8a2 --- /dev/null +++ b/praktikum/ingredient.py @@ -0,0 +1,20 @@ +class Ingredient: + """ + Модель ингредиента. + Ингредиент: начинка или соус. + У ингредиента есть тип (начинка или соус), название и цена. + """ + + def __init__(self, ingredient_type: str, name: str, price: float): + self.type = ingredient_type + self.name = name + self.price = price + + def get_price(self) -> float: + return self.price + + def get_name(self) -> str: + return self.name + + def get_type(self) -> str: + return self.type diff --git a/praktikum/ingredient_types.py b/praktikum/ingredient_types.py new file mode 100644 index 000000000..34940ad5d --- /dev/null +++ b/praktikum/ingredient_types.py @@ -0,0 +1,7 @@ +""" +Перечисление с типами ингредиентов. +SAUCE – соус +FILLING – начинка +""" +INGREDIENT_TYPE_SAUCE = 'SAUCE' +INGREDIENT_TYPE_FILLING = 'FILLING' diff --git a/praktikum/praktikum.py b/praktikum/praktikum.py new file mode 100644 index 000000000..ec522fa6d --- /dev/null +++ b/praktikum/praktikum.py @@ -0,0 +1,41 @@ +from typing import List + +from praktikum.bun import Bun +from praktikum.burger import Burger +from praktikum.database import Database +from praktikum.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]) + burger.add_ingredient(ingredients[4]) + burger.add_ingredient(ingredients[3]) + burger.add_ingredient(ingredients[5]) + + # Переместим слой с ингредиентом + burger.move_ingredient(2, 1) + + # Удалим ингредиент + burger.remove_ingredient(3) + + # Распечатаем рецепт бургера + print(burger.get_receipt()) + + +if __name__ == "__main__": + main() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..e69de29bb diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/data/__init__.py b/tests/data/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/data/test_data.py b/tests/data/test_data.py new file mode 100644 index 000000000..5bcba71b7 --- /dev/null +++ b/tests/data/test_data.py @@ -0,0 +1,28 @@ +# buns +BLACK_BUN_NAME = "black bun" +BLACK_BUN_PRICE = 100 + +WHITE_BUN_NAME = "white bun" +WHITE_BUN_PRICE = 200 + +RED_BUN_NAME = "red bun" +RED_BUN_PRICE = 300 + +# ingredients +HOT_SAUCE_NAME = "hot sauce" +HOT_SAUCE_PRICE = 50 + +CUTLET_NAME = "cutlet" +CUTLET_PRICE = 200 + +SAUSAGE_NAME = "sausage" +SAUSAGE_PRICE = 300 + +# receipt +EXPECTED_RECEIPT_SINGLE_SAUCE = ( + "(==== black bun ====)\n" + "= sauce hot sauce =\n" + "(==== black bun ====)\n" + "\n" + "Price: 250" +) diff --git a/tests/test_bun.py b/tests/test_bun.py new file mode 100644 index 000000000..a17d7036f --- /dev/null +++ b/tests/test_bun.py @@ -0,0 +1,28 @@ +from praktikum.bun import Bun + +from tests.data.test_data import ( + BLACK_BUN_NAME, + BLACK_BUN_PRICE, + WHITE_BUN_NAME, + WHITE_BUN_PRICE, + RED_BUN_NAME, + RED_BUN_PRICE +) + + + +class TestBun: + + def test_bun_init(self): + bun = Bun(BLACK_BUN_NAME, BLACK_BUN_PRICE) + + assert bun.name == BLACK_BUN_NAME + assert bun.price == BLACK_BUN_PRICE + + def test_get_name(self): + bun = Bun(WHITE_BUN_NAME, WHITE_BUN_PRICE) + assert bun.get_name() == WHITE_BUN_NAME + + def test_get_price(self): + bun = Bun(RED_BUN_NAME, RED_BUN_PRICE) + assert bun.get_price() == RED_BUN_PRICE diff --git a/tests/test_burger.py b/tests/test_burger.py new file mode 100644 index 000000000..c61984057 --- /dev/null +++ b/tests/test_burger.py @@ -0,0 +1,109 @@ +from praktikum.burger import Burger +from praktikum.bun import Bun +from praktikum.ingredient import Ingredient +from praktikum.ingredient_types import ( + INGREDIENT_TYPE_SAUCE, + INGREDIENT_TYPE_FILLING +) + +from tests.data.test_data import ( + BLACK_BUN_NAME, + BLACK_BUN_PRICE, + HOT_SAUCE_NAME, + HOT_SAUCE_PRICE, + CUTLET_NAME, + CUTLET_PRICE, + EXPECTED_RECEIPT_SINGLE_SAUCE +) + + +class TestBurger: + + def test_set_buns(self): + burger = Burger() + bun = Bun(BLACK_BUN_NAME, BLACK_BUN_PRICE) + + burger.set_buns(bun) + + assert burger.bun == bun + + def test_add_ingredient(self): + burger = Burger() + ingredient = Ingredient( + INGREDIENT_TYPE_SAUCE, + HOT_SAUCE_NAME, + HOT_SAUCE_PRICE + ) + + burger.add_ingredient(ingredient) + + assert ingredient in burger.ingredients + + def test_remove_ingredient(self): + burger = Burger() + ingredient = Ingredient( + INGREDIENT_TYPE_FILLING, + CUTLET_NAME, + CUTLET_PRICE + ) + + burger.add_ingredient(ingredient) + burger.remove_ingredient(0) + + assert burger.ingredients == [] + + def test_move_ingredient(self): + burger = Burger() + + ingredient1 = Ingredient( + INGREDIENT_TYPE_SAUCE, + HOT_SAUCE_NAME, + HOT_SAUCE_PRICE + ) + ingredient2 = Ingredient( + INGREDIENT_TYPE_FILLING, + CUTLET_NAME, + CUTLET_PRICE + ) + + burger.add_ingredient(ingredient1) + burger.add_ingredient(ingredient2) + burger.move_ingredient(0, 1) + + assert burger.ingredients == [ingredient2, ingredient1] + + def test_get_price(self): + burger = Burger() + bun = Bun(BLACK_BUN_NAME, BLACK_BUN_PRICE) + + burger.set_buns(bun) + burger.add_ingredient( + Ingredient( + INGREDIENT_TYPE_SAUCE, + HOT_SAUCE_NAME, + HOT_SAUCE_PRICE + ) + ) + burger.add_ingredient( + Ingredient( + INGREDIENT_TYPE_FILLING, + CUTLET_NAME, + CUTLET_PRICE + ) + ) + + assert burger.get_price() == 450 + + def test_get_receipt(self): + burger = Burger() + bun = Bun(BLACK_BUN_NAME, BLACK_BUN_PRICE) + ingredient = Ingredient( + INGREDIENT_TYPE_SAUCE, + HOT_SAUCE_NAME, + HOT_SAUCE_PRICE + ) + + burger.set_buns(bun) + burger.add_ingredient(ingredient) + + assert burger.get_receipt() == EXPECTED_RECEIPT_SINGLE_SAUCE diff --git a/tests/test_database.py b/tests/test_database.py new file mode 100644 index 000000000..4c18eff0c --- /dev/null +++ b/tests/test_database.py @@ -0,0 +1,25 @@ +from praktikum.database import Database +from praktikum.bun import Bun +from praktikum.ingredient import Ingredient + + +class TestDatabase: + def test_database_init(self): + database = Database() + + assert len(database.buns) == 3 + assert len(database.ingredients) == 6 + + def test_available_buns(self): + database = Database() + buns = database.available_buns() + + assert isinstance(buns, list) + assert all(isinstance(bun, Bun) for bun in buns) + + def test_available_ingredients(self): + database = Database() + ingredients = database.available_ingredients() + + assert isinstance(ingredients, list) + assert all(isinstance(ingredient, Ingredient) for ingredient in ingredients) diff --git a/tests/test_ingredient.py b/tests/test_ingredient.py new file mode 100644 index 000000000..5feed1f97 --- /dev/null +++ b/tests/test_ingredient.py @@ -0,0 +1,53 @@ +from praktikum.ingredient import Ingredient +from praktikum.ingredient_types import ( + INGREDIENT_TYPE_SAUCE, + INGREDIENT_TYPE_FILLING +) + +from tests.data.test_data import ( + HOT_SAUCE_NAME, + HOT_SAUCE_PRICE, + CUTLET_NAME, + CUTLET_PRICE, + SAUSAGE_NAME, + SAUSAGE_PRICE +) + + + +class TestIngredient: + + def test_ingredient_init(self): + ingredient = Ingredient( + INGREDIENT_TYPE_SAUCE, + HOT_SAUCE_NAME, + HOT_SAUCE_PRICE + ) + + assert ingredient.type == INGREDIENT_TYPE_SAUCE + assert ingredient.name == HOT_SAUCE_NAME + assert ingredient.price == HOT_SAUCE_PRICE + + def test_get_price(self): + ingredient = Ingredient( + INGREDIENT_TYPE_FILLING, + CUTLET_NAME, + CUTLET_PRICE + ) + assert ingredient.get_price() == CUTLET_PRICE + + def test_get_name(self): + ingredient = Ingredient( + INGREDIENT_TYPE_FILLING, + SAUSAGE_NAME, + SAUSAGE_PRICE + ) + assert ingredient.get_name() == SAUSAGE_NAME + + def test_get_type(self): + ingredient = Ingredient( + INGREDIENT_TYPE_SAUCE, + HOT_SAUCE_NAME, + HOT_SAUCE_PRICE + ) + assert ingredient.get_type() == INGREDIENT_TYPE_SAUCE