diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..d4c50a593 --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +.pytest_cache +.coverage + +# Environments +.env +.envrc +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.vscode +.venv + +.vscode +htmlcov \ No newline at end of file diff --git a/README.md b/README.md index 272081708..39a801e06 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,16 @@ ## Задание 1: Юнит-тесты -### Автотесты для проверки программы, которая помогает заказать бургер в Stellar Burgers +### Автотесты для проверки класса Burger в Stellar Burgers ### Реализованные сценарии -Созданы юнит-тесты, покрывающие классы `Bun`, `Burger`, `Ingredient`, `Database` +Созданы юнит-тесты, покрывающие класс `Burger`. Процент покрытия 100% (отчет: `htmlcov/index.html`) ### Структура проекта -- `praktikum` - пакет, содержащий код программы -- `tests` - пакет, содержащий тесты, разделенные по классам. Например, `bun_test.py`, `burger_test.py` и т.д. +- `tests` - пакет, содержащий тесты `burger_test.py` ### Запуск автотестов @@ -21,4 +20,5 @@ **Запуск автотестов и создание HTML-отчета о покрытии** -> `$ pytest --cov=praktikum --cov-report=html` +> `$ pytest --cov=burger --cov-report=html tests/` + diff --git a/__init__.py b/Tests/__init__.py similarity index 100% rename from __init__.py rename to Tests/__init__.py diff --git a/Tests/test_burger.py b/Tests/test_burger.py new file mode 100644 index 000000000..b041a4171 --- /dev/null +++ b/Tests/test_burger.py @@ -0,0 +1,69 @@ +from burger import Burger +from conftest import * +import pytest + +class TestBurger: + #Проверка работы метода set_buns, добавляющего булочку в бургер. + def test_set_buns_success(self, mock_bun): + burger = Burger() + burger.set_buns(mock_bun) + assert burger.bun == mock_bun + + #Проверка работы метода add_ingredient, добавляющего ингредиенты в бургер + #С помощью параметризации выполняем три теста: проверяем по очереди добавление соуса и двух разных начинок. + @pytest.mark.parametrize('ingredients, added_ingredient', [ + [Data1.sauce_name, Data1.sauce_name], + [Data1.filling_name, Data1.filling_name], + [Data2.filling_name, Data2.filling_name] + ] + ) + def test_add_ingredient_success(self, ingredients, added_ingredient): + burger = Burger() + burger.add_ingredient(ingredients) + assert burger.ingredients == [added_ingredient] + + #Проверка работы метода remove_ingredient, удаляющего ингредиент из бургера. + #С помощью параметризации выполняем два теста: проверяем по очереди удаление соуса и начинки. + @pytest.mark.parametrize('ingredients, removed_ingredient', [ + [Data1.sauce_name, Data1.sauce_name], + [Data2.filling_name, Data2.filling_name] + ] + ) + def test_remove_ingredient_success(self, ingredients, removed_ingredient, mock_filling): + burger = Burger() + burger.add_ingredient(mock_filling) + burger.add_ingredient(ingredients) + burger.remove_ingredient(1) + assert removed_ingredient not in burger.ingredients and mock_filling in burger.ingredients + + #Проверка работы метода move_ingredient, перемещающего ингредиенты в бургере. + def test_move_ingredient_success(self, mock_sauce, mock_filling): + burger = Burger() + burger.add_ingredient(mock_sauce) + burger.add_ingredient(mock_filling) + burger.move_ingredient(0, 1) + assert len(burger.ingredients) == 2 + assert burger.ingredients[0] == mock_filling and burger.ingredients[1] == mock_sauce + + #Проверка работы метода get_price, высчитывающего конечную стоимость бургера. + def test_get_price_burger_success(self, mock_bun_2, mock_sauce_2, mock_filling_2): + burger = Burger() + burger.set_buns(mock_bun_2) + burger.add_ingredient(mock_sauce_2) + burger.add_ingredient(mock_filling_2) + assert burger.get_price() == Data2.burger_final_cost + + #Проверка работы метода get_receipt, получающего рецепт собранного бургера и его стоимость. + def test_get_receipt_success(self, mock_bun, mock_sauce, mock_filling, mock_filling_2): + burger = Burger() + burger.set_buns(mock_bun) + burger.add_ingredient(mock_sauce) + burger.add_ingredient(mock_filling) + burger.add_ingredient(mock_filling_2) + assert burger.get_receipt() == ('(==== Флюоресцентная булка R2-D3 ====)\n' + '= sauce Соус традиционный галактический =\n' + '= filling Мясо бессмертных моллюсков Protostomia =\n' + '= filling Сыр с астероидной плесенью =\n' + '(==== Флюоресцентная булка R2-D3 ====)\n' + '\n' + f'Price: {burger.get_price()}') \ No newline at end of file diff --git a/burger.py b/burger.py index 2b3b6a88b..3f71aaa29 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: diff --git a/conftest.py b/conftest.py new file mode 100644 index 000000000..6abd89b27 --- /dev/null +++ b/conftest.py @@ -0,0 +1,61 @@ +from database import Database +from unittest.mock import Mock +from data import Data1, Data2 +import pytest + + +@pytest.fixture +def mock_bun(): + mock_for_bun = Mock() + mock_for_bun.get_name.return_value = Data1.bun_name + mock_for_bun.get_price.return_value = Data1.bun_price + return mock_for_bun + + +@pytest.fixture +def mock_bun_2(): + mock_for_bun_2 = Mock() + mock_for_bun_2.get_name.return_value = Data2.bun_name + mock_for_bun_2.get_price.return_value = Data2.bun_price + return mock_for_bun_2 + + +@pytest.fixture +def mock_sauce(): + mock_for_sauce = Mock() + mock_for_sauce.get_name.return_value = Data1.sauce_name + mock_for_sauce.get_price.return_value = Data1.sauce_price + mock_for_sauce.get_type.return_value = Data1.sauce_type + return mock_for_sauce + + +@pytest.fixture +def mock_sauce_2(): + mock_for_sauce_2 = Mock() + mock_for_sauce_2.get_name.return_value = Data2.sauce_name + mock_for_sauce_2.get_price.return_value = Data2.sauce_price + mock_for_sauce_2.get_type.return_value = Data2.sauce_type + return mock_for_sauce_2 + + +@pytest.fixture +def mock_filling(): + mock_for_filling = Mock() + mock_for_filling.get_name.return_value = Data1.filling_name + mock_for_filling.get_price.return_value = Data1.filling_price + mock_for_filling.get_type.return_value = Data1.filling_type + return mock_for_filling + + +@pytest.fixture +def mock_filling_2(): + mock_for_filling_2 = Mock() + mock_for_filling_2.get_name.return_value = Data2.filling_name + mock_for_filling_2.get_price.return_value = Data2.filling_price + mock_for_filling_2.get_type.return_value = Data2.filling_type + return mock_for_filling_2 + + +@pytest.fixture +def db(): + return Database() \ No newline at end of file diff --git a/data.py b/data.py new file mode 100644 index 000000000..d795b6ba3 --- /dev/null +++ b/data.py @@ -0,0 +1,49 @@ +from ingredient_types import INGREDIENT_TYPE_SAUCE, INGREDIENT_TYPE_FILLING + + +class Data1: + bun_name = 'Флюоресцентная булка R2-D3' + bun_price = 988 + + sauce_type = INGREDIENT_TYPE_SAUCE + sauce_name = 'Соус традиционный галактический' + sauce_price = 15 + + filling_type = INGREDIENT_TYPE_FILLING + filling_name = 'Мясо бессмертных моллюсков Protostomia' + filling_price = 1350 + + burger_final_cost = bun_price * 2 + sauce_price + filling_price + + +class Data2: + bun_name = 'Краторная булка N-200i' + bun_price = 1255 + + sauce_type = INGREDIENT_TYPE_SAUCE + sauce_name = 'Соус с шипами Антарианского плоскоходца' + sauce_price = 88 + + filling_type = INGREDIENT_TYPE_FILLING + filling_name = 'Сыр с астероидной плесенью' + filling_price = 4142 + + burger_final_cost = bun_price * 2 + sauce_price + filling_price + + +class TestDataBase: + test_data_base_buns = [ + [0, 'black bun', 100], + [1, 'white bun', 200], + [2, 'red bun', 300] + ] + + test_data_base_ingredients = [ + [0, INGREDIENT_TYPE_SAUCE, 'hot sauce', 100], + [1, INGREDIENT_TYPE_SAUCE, 'sour cream', 200], + [2, INGREDIENT_TYPE_SAUCE, 'chili sauce', 300], + [3, INGREDIENT_TYPE_FILLING, 'cutlet', 100], + [4, INGREDIENT_TYPE_FILLING, 'dinosaur', 200], + [5, INGREDIENT_TYPE_FILLING, 'sausage', 300] + + ] \ 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..88b77abd1 100644 --- a/praktikum.py +++ b/praktikum.py @@ -1,9 +1,9 @@ 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(): diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..8aab4dd58 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,54 @@ +asttokens==3.0.0 +attrs==25.4.0 +certifi==2025.11.12 +cffi==2.0.0 +colorama==0.4.6 +comm==0.2.3 +coverage==7.12.0 +debugpy==1.8.17 +decorator==5.2.1 +executing==2.2.1 +Faker==39.0.0 +h11==0.16.0 +idna==3.11 +iniconfig==2.3.0 +ipykernel==6.30.1 +ipython==9.6.0 +ipython_pygments_lexers==1.1.1 +jedi==0.19.2 +jupyter_client==8.6.3 +jupyter_core==5.8.1 +matplotlib-inline==0.1.7 +nest-asyncio==1.6.0 +outcome==1.3.0.post0 +packaging==25.0 +parso==0.8.5 +platformdirs==4.4.0 +pluggy==1.6.0 +prompt_toolkit==3.0.52 +psutil==7.1.0 +pure_eval==0.2.3 +pycparser==2.23 +Pygments==2.19.2 +PySocks==1.7.1 +pytest==9.0.1 +pytest-cov==7.0.0 +pyTesy==0.0.3 +python-dateutil==2.9.0.post0 +pywin32==311 +pyzmq==27.1.0 +selenium==4.39.0 +six==1.17.0 +sniffio==1.3.1 +sortedcontainers==2.4.0 +stack-data==0.6.3 +tornado==6.5.2 +traitlets==5.14.3 +trio==0.32.0 +trio-websocket==0.12.2 +typing_extensions==4.15.0 +tzdata==2025.3 +urllib3==2.6.2 +wcwidth==0.2.14 +websocket-client==1.9.0 +wsproto==1.3.2