From cad872154589e30b94ca2c6486f5847e0e2532b9 Mon Sep 17 00:00:00 2001 From: Victoriya Z Date: Sat, 10 Jan 2026 18:20:06 +0300 Subject: [PATCH 1/2] =?UTF-8?q?=D0=B7=D0=B0=D0=B2=D0=B5=D1=80=D1=88=D0=B5?= =?UTF-8?q?=D0=BD=D0=BE=20=D0=B7=D0=B0=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5=201?= =?UTF-8?q?=20=E2=80=94=20Burger=20=D0=BF=D0=BE=D0=BA=D1=80=D1=8B=D1=82=20?= =?UTF-8?q?=D1=82=D0=B5=D1=81=D1=82=D0=B0=D0=BC=D0=B8,=20100%=20coverage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 28 +++++ README.md | 46 +++++--- 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 praktikum.py => praktikum/praktikum.py | 0 requirements.txt | Bin 0 -> 276 bytes __init__.py => tests/__init__.py | 0 tests/test_burger.py | 99 ++++++++++++++++++ 11 files changed, 161 insertions(+), 12 deletions(-) create mode 100644 .gitignore 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%) rename praktikum.py => praktikum/praktikum.py (100%) create mode 100644 requirements.txt rename __init__.py => tests/__init__.py (100%) create mode 100644 tests/test_burger.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..48432ce70 --- /dev/null +++ b/.gitignore @@ -0,0 +1,28 @@ +# Виртуальное окружение +.venv/ +venv/ +env/ + +# Кэш Python +__pycache__/ +*.pyc +*.pyo +*.pyd +.Python +.ipynb_checkpoints + +# Coverage +.coverage + +# IDE +.vscode/ +.idea/ +*.swp +*.swo + +# ОС +.DS_Store +Thumbs.db + +# pytest +.pytest_cache/ \ No newline at end of file diff --git a/README.md b/README.md index 272081708..e68ce53d4 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,46 @@ -## Задание 1: Юнит-тесты +Задание 1: Юнит-тесты +Автотесты для проверки программы, которая помогает заказать бургер в Stellar Burgers -### Автотесты для проверки программы, которая помогает заказать бургер в Stellar Burgers +Реализованные сценарии -### Реализованные сценарии +Созданы юнит-тесты, покрывающие классы `Burger` +Процент покрытия 100% (отчет: `htmlcov/index.html`) -Созданы юнит-тесты, покрывающие классы `Bun`, `Burger`, `Ingredient`, `Database` -Процент покрытия 100% (отчет: `htmlcov/index.html`) +Проверены: -### Структура проекта +Установка булочки (set_buns) +Добавление ингредиентов (add_ingredient) +Удаление ингредиентов по индексу (remove_ingredient) +Перемещение ингредиентов (move_ingredient) +Расчёт итоговой стоимости (get_price) +Формирование чека (get_receipt) — здесь использован unittest.mock.Mock -- `praktikum` - пакет, содержащий код программы -- `tests` - пакет, содержащий тесты, разделенные по классам. Например, `bun_test.py`, `burger_test.py` и т.д. +DIPLOM_1/ +├── htmlcov/ # Отчет о покрытии +├── praktikum/ # Основной код приложения +│ ├── __init__.py +│ ├── bun.py +│ ├── burger.py +│ ├── database.py +│ ├── ingredient.py +│ ├── ingredient_types.py +│ └── praktikum.py +├── tests/ # Тесты +│ ├── __init__.py +│ └── test_burger.py +├── .gitignore +├── README.md # описание проекта +└── requirements.txt # Зависимости -### Запуск автотестов -**Установка зависимостей** +Установка зависимостей > `$ pip install -r requirements.txt` -**Запуск автотестов и создание HTML-отчета о покрытии** - +Запуск автотестов и создание HTML-отчета о покрытии > `$ pytest --cov=praktikum --cov-report=html` + +Примечание +Bun и Ingredient — простые объекты данных без побочных эффектов, поэтому в большинстве тестов они используются «как есть». +Мок применяется только в тесте get_receipt(), чтобы изолировать форматирование чека от реализации других классов и гарантировать, что тест проверяет именно логику вывода, а не работу зависимостей. 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/praktikum.py b/praktikum/praktikum.py similarity index 100% rename from praktikum.py rename to praktikum/praktikum.py diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..bfc2333d3d950309d6d92baeed845784e3e5ca13 GIT binary patch literal 276 zcmZXPT?)c55C*?z!J{Zm)rt?^!7G#!gIKF*6?%E=?AjJV!X_az*`NMh>8hHztJH%H2-ul%r#D9*0;|O$)za_ literal 0 HcmV?d00001 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..5f3714871 --- /dev/null +++ b/tests/test_burger.py @@ -0,0 +1,99 @@ +import pytest +from unittest.mock import Mock + +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 + + +class TestBurger: + + @pytest.mark.parametrize("name, price", [("black bun", 100),("white bun", 200),]) + def test_set_buns_sets_bun_successfully(self, name, price): + burger = Burger() + bun = Bun(name, price) + burger.set_buns(bun) + assert burger.bun is bun + + @pytest.mark.parametrize("type, name, price", [(INGREDIENT_TYPE_SAUCE, "hot sauce", 100),(INGREDIENT_TYPE_FILLING, "cutlet", 100),(INGREDIENT_TYPE_SAUCE, "chili sauce", 300),]) + def test_add_ingredient_successfully(self, type, name, price): + burger = Burger() + ingredient = Ingredient(type, name, price) + burger.add_ingredient(ingredient) + assert ingredient in burger.ingredients + + def test_remove_ingredient_removes_ingredient_by_index_successfully(self): + burger = Burger() + cutlet = Ingredient(INGREDIENT_TYPE_FILLING, "cutlet", 100) + dinosaur = Ingredient(INGREDIENT_TYPE_FILLING, "dinosaur", 200) + sauce = Ingredient(INGREDIENT_TYPE_SAUCE, "chili sauce", 300) + burger.add_ingredient(cutlet) + burger.add_ingredient(dinosaur) + burger.add_ingredient(sauce) + burger.remove_ingredient(1) + assert len(burger.ingredients) == 2 + assert cutlet in burger.ingredients + assert sauce in burger.ingredients + assert dinosaur not in burger.ingredients + + def test_move_ingredient_moves_ingredient_by_index_successfully(self): + burger = Burger() + sauce = Ingredient(INGREDIENT_TYPE_SAUCE, "chili sauce", 300) + cutlet = Ingredient(INGREDIENT_TYPE_FILLING, "cutlet", 100) + dinosaur = Ingredient(INGREDIENT_TYPE_FILLING, "dinosaur", 200) + hot_sauce = Ingredient(INGREDIENT_TYPE_SAUCE, "hot sauce", 100) + burger.add_ingredient(sauce) + burger.add_ingredient(cutlet) + burger.add_ingredient(dinosaur) + burger.add_ingredient(hot_sauce) + burger.move_ingredient(2,3) + assert len(burger.ingredients) == 4 + assert burger.ingredients[0] is sauce + assert burger.ingredients[1] is cutlet + assert burger.ingredients[2] is hot_sauce + assert burger.ingredients[3] is dinosaur + + + @pytest.mark.parametrize('bun_name, bun_price, ingredients_data, expected_price', + [("black bun", 100, [(INGREDIENT_TYPE_FILLING, "cutlet", 100)], 300), + ("black bun", 100, [], 200), + ("white bun", 200, [(INGREDIENT_TYPE_FILLING, "dinosaur", 200), (INGREDIENT_TYPE_SAUCE, "hot sauce", 100)], 700)]) + def test_get_price_cost_of_a_ready_made_burger(self, bun_name, bun_price, ingredients_data, expected_price ): + burger = Burger() + bun = Bun(bun_name, bun_price) + burger.set_buns(bun) + + for type, name, price in ingredients_data: + ingredient = Ingredient(type, name, price) + burger.add_ingredient(ingredient) + + price = burger.get_price() + assert price == expected_price + + + def test_get_receipt_uses_mocked_bun_and_ingredient(self): + bun="red bun" + bun_price=300 + + ingredient_type=INGREDIENT_TYPE_FILLING + ingredient_name="cutlet" + ingredient_price=200 + + mock_bun = Mock() + mock_bun.get_name.return_value = bun + mock_bun.get_price.return_value = bun_price + + mock_ingredient = Mock() + mock_ingredient.get_type.return_value = ingredient_type + mock_ingredient.get_name.return_value = ingredient_name + mock_ingredient.get_price.return_value = ingredient_price + + burger = Burger() + burger.set_buns(mock_bun) + burger.add_ingredient(mock_ingredient) + + receipt = burger.get_receipt() + + expected = f"(==== {bun} ====)\n= {ingredient_type.lower()} {ingredient_name} =\n(==== {bun} ====)\n\nPrice: {bun_price*2 + ingredient_price}" + assert receipt == expected \ No newline at end of file From d52603b00a83dfb1cbae6900de27016d76cf6db7 Mon Sep 17 00:00:00 2001 From: Victoriya Z Date: Thu, 22 Jan 2026 12:02:37 +0300 Subject: [PATCH 2/2] docs: update README with coverage info and restore htmlcov to .gitignore --- .gitignore | 1 + README.md | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 48432ce70..20623a09c 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ __pycache__/ # Coverage .coverage +htmlcov/ # IDE .vscode/ diff --git a/README.md b/README.md index e68ce53d4..130fb8b3c 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,17 @@ Реализованные сценарии Созданы юнит-тесты, покрывающие классы `Burger` -Процент покрытия 100% (отчет: `htmlcov/index.html`) +Класс `Burger` покрыт на 100% — согласно отчёту `htmlcov/index.html`. +Name Stmts Miss Cover +--------------------------------------------------- +praktikum\bun.py 8 1 88% +praktikum\burger.py 27 0 100% +praktikum\database.py 21 21 0% +praktikum\ingredient.py 11 2 82% +praktikum\ingredient_types.py 2 0 100% +praktikum\praktikum.py 20 20 0% +--------------------------------------------------- +TOTAL 89 44 51% Проверены: