From 65e1afb25acde08d7d170bd77c2203272b5fe7da Mon Sep 17 00:00:00 2001 From: Maxim Hozhaynov Date: Fri, 1 May 2026 15:05:52 +0300 Subject: [PATCH 1/2] first commit --- .gitignore | 220 ++++++++++++++++++ __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 praktikum.py => praktikum/praktikum.py | 0 requirements.txt | 2 + tests/conftest.py | 6 + tests/test_burger.py | 103 ++++++++ 11 files changed, 331 insertions(+) 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%) rename praktikum.py => praktikum/praktikum.py (100%) create mode 100644 requirements.txt create mode 100644 tests/conftest.py create mode 100644 tests/test_burger.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..bbaa4921f --- /dev/null +++ b/.gitignore @@ -0,0 +1,220 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[codz] +*$py.class + +# C extensions +*.so +.vscode +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py.cover +*.lcov +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +# Pipfile.lock + +# UV +# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# uv.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +# poetry.lock +# poetry.toml + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python. +# https://pdm-project.org/en/latest/usage/project/#working-with-version-control +# pdm.lock +# pdm.toml +.pdm-python +.pdm-build/ + +# pixi +# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control. +# pixi.lock +# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one +# in the .venv directory. It is recommended not to include this directory in version control. +.pixi/* +!.pixi/config.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule* +celerybeat.pid + +# Redis +*.rdb +*.aof +*.pid + +# RabbitMQ +mnesia/ +rabbitmq/ +rabbitmq-data/ + +# ActiveMQ +activemq-data/ + +# SageMath parsed files +*.sage.py + +# Environments +.env +.envrc +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +# .idea/ + +# Abstra +# Abstra is an AI-powered process automation framework. +# Ignore directories containing user credentials, local state, and settings. +# Learn more at https://abstra.io/docs +.abstra/ + +# Visual Studio Code +# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore +# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore +# and can be added to the global gitignore or merged into this file. However, if you prefer, +# you could uncomment the following to ignore the entire vscode folder +# .vscode/ +# Temporary file for partial code execution +tempCodeRunnerFile.py + +# Ruff stuff: +.ruff_cache/ + +# PyPI configuration file +.pypirc + +# Marimo +marimo/_static/ +marimo/_lsp/ +__marimo__/ + +# Streamlit +.streamlit/secrets.toml 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/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 000000000..9955deccd --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +pytest +pytest-cov diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 000000000..17cdbe1f9 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,6 @@ +from pathlib import Path +import sys + +ROOT = Path(__file__).resolve().parents[1] +if str(ROOT) not in sys.path: + sys.path.insert(0, str(ROOT)) diff --git a/tests/test_burger.py b/tests/test_burger.py new file mode 100644 index 000000000..3c15f4fad --- /dev/null +++ b/tests/test_burger.py @@ -0,0 +1,103 @@ +import pytest +from unittest.mock import Mock + +from praktikum.burger import Burger + + +@pytest.fixture +def burger(): + return Burger() + + +@pytest.fixture +def bun_mock(): + bun = Mock() + bun.get_name.return_value = "black bun" + bun.get_price.return_value = 200 + return bun + + +@pytest.mark.parametrize("name, price", [("cheese", 50), ("sauce", 25), ("bacon", 100)]) +def test_add_ingredient_appends_in_order(burger, name, price): + ingredient = Mock() + ingredient.get_name.return_value = name + ingredient.get_price.return_value = price + + burger.add_ingredient(ingredient) + + assert burger.ingredients[-1] is ingredient + + +def test_set_buns_sets_bun_instance(burger, bun_mock): + burger.set_buns(bun_mock) + + assert burger.bun is bun_mock + + +def test_remove_ingredient_by_index(burger): + first = Mock() + second = Mock() + burger.ingredients = [first, second] + + burger.remove_ingredient(0) + + assert burger.ingredients == [second] + + +@pytest.mark.parametrize( + "start, index, new_index, expected", + [ + (["a", "b", "c"], 0, 2, ["b", "c", "a"]), + (["a", "b", "c"], 2, 0, ["c", "a", "b"]), + ], +) +def test_move_ingredient_reorders_items(burger, start, index, new_index, expected): + burger.ingredients = start.copy() + + burger.move_ingredient(index, new_index) + + assert burger.ingredients == expected + + +def test_get_price_uses_bun_price_twice_and_all_ingredients(burger, bun_mock): + ingredient_1 = Mock() + ingredient_1.get_price.return_value = 50 + ingredient_2 = Mock() + ingredient_2.get_price.return_value = 25 + + burger.set_buns(bun_mock) + burger.add_ingredient(ingredient_1) + burger.add_ingredient(ingredient_2) + + total = burger.get_price() + + assert total == 475 + bun_mock.get_price.assert_called_once_with() + ingredient_1.get_price.assert_called_once_with() + ingredient_2.get_price.assert_called_once_with() + + +def test_get_receipt_returns_expected_text_and_calls_dependencies(burger, bun_mock): + ingredient = Mock() + ingredient.get_type.return_value = "SAUCE" + ingredient.get_name.return_value = "hot chili" + ingredient.get_price.return_value = 30 + + burger.set_buns(bun_mock) + burger.add_ingredient(ingredient) + + receipt = burger.get_receipt() + + assert receipt == "\n".join( + [ + "(==== black bun ====)", + "= sauce hot chili =", + "(==== black bun ====)\n", + "Price: 430", + ] + ) + assert bun_mock.get_name.call_count == 2 + ingredient.get_type.assert_called_once_with() + ingredient.get_name.assert_called_once_with() + bun_mock.get_price.assert_called_once_with() + ingredient.get_price.assert_called_once_with() From dbfc8ad68c4fdac7ae6df9c1f381fd894e0b5bb9 Mon Sep 17 00:00:00 2001 From: Maxim Hozhaynov Date: Sat, 2 May 2026 15:26:40 +0300 Subject: [PATCH 2/2] =?UTF-8?q?=D0=A1=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=B0=D0=B2=D1=82=D0=BE=D1=82=D0=B5=D1=81=D1=82=D0=BE?= =?UTF-8?q?=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 272081708..c71674816 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ ### Структура проекта - `praktikum` - пакет, содержащий код программы -- `tests` - пакет, содержащий тесты, разделенные по классам. Например, `bun_test.py`, `burger_test.py` и т.д. +- `tests` - пакет, содержащий тесты. ### Запуск автотестов