Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions pizza_project/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Pizza project

Для работы в файле cli.py нужно установить пакет **click** в терминале: ```pip install click```

Для того чтобы вывести с его помощью меню пишем: ```python cli.py menu```

Получаем:

```- Margherita 🧀: tomato sauce, mozzarella, tomatoes```

```- Pepperoni 🍕: tomato sauce, mozzarella, pepperoni```

```- Hawaiian 🍍: tomato sauce, mozzarella, chicken, pineapples```

------
Чтобы посмотреть на этапы приготовления нашей пиццы: ```python cli.py order peperoni --delivery```

Например, можем получить вывод такого типы (но время может быть другое)

```🔪 приготовили за 4 минут!```

```🛵 доставили за 9 минут!```

------
Переходим к тестированию нашего проекта.

Для запска тестовых функций в терпинале запускаем: ```python -m pytest -v testing.py```

Получем:

PS D:\pythonProject1> python -m pytest -v testing.py

=================================== test session starts===================================

platform win32 -- Python 3.10.7, pytest-7.4.3, pluggy-1.3.0 -- D:\python\python.exe

cachedir: .pytest_cache

rootdir: D:\pythonProject1

plugins: cov-4.1.0

=================================== 10 passed in 0.09s ===================================
43 changes: 43 additions & 0 deletions pizza_project/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import click
from services import bake, deliver, pickup
from pizza import Pizza


@click.group()
def cli():
pass


@cli.command()
@click.option("--delivery", default=False, is_flag=True)
@click.argument("pizza", nargs=1)
def order(pizza: str, delivery: bool) -> None:
"""
Функция позволяет через терминал осуществить приготовление и доставку пиццы
с указанием временных затрат на каждом этапе
:param pizza: str
:param delivery: bool
:return: None
"""
for pizza_name in Pizza.__subclasses__():
if pizza_name().__class__.__name__.lower() == pizza:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Лучше избегать лишней вложенности. Здесь можно было сначала проверить, что pizza не из меню -> вызвать ошибку, и потом уже без вложенности продолжать функцию

bake(pizza_name())
if delivery:
deliver(pizza_name())
else:
pickup(pizza_name())


@cli.command()
def menu() -> None:
"""
Функция позволяет через терминал осуществить посмотреть на меню
:return: None
"""
for pizza in Pizza.__subclasses__():
recipe = pizza().dict()
print('- ', *recipe.keys(), ': ', *recipe.values(), sep='')


if __name__ == '__main__':
cli()
54 changes: 54 additions & 0 deletions pizza_project/pizza.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
class Pizza:
"""Базовый класс для всех видов пицц"""

def __init__(self, size: str = 'L', name: str = None, extra_ingredients: list = []):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Размер пиццы в итоге нигде не задаётся

if size not in ['L', 'XL']:
raise ValueError("У нас нет пиццы такого размера. "
"Размер может быть только L или XL.")
self.size = size
self.name = name
self.ingredients = ["tomato sauce", "mozzarella"]
self.ingredients.extend(extra_ingredients)

def dict(self) -> dict[str]:
"""
Метод выводит рецепт в виде словаря
:return: dict[str]
"""
return {self.__dict__['name']: ', '.join(self.__dict__['ingredients'])}

def __eq__(self, other) -> bool:
"""
Метод позволяет сравнить две пиццы на равенство
:param self: Pizza
:param other: Pizza
:return: bool
"""
return self.ingredients == other.ingredients and self.size == other.size


class Margherita(Pizza):
"""Класс пиццы Маргарита"""

def __init__(self, size: str = "L"):
self.name = "Margherita 🧀"
self.extra_ingredients = ["tomatoes"]
super().__init__(size, self.name, self.extra_ingredients)


class Pepperoni(Pizza):
"""Класс пиццы Пепперони"""

def __init__(self, size: str = "L"):
self.name = "Pepperoni 🍕"
self.extra_ingredients = ["pepperoni"]
super().__init__(size, self.name, self.extra_ingredients)


class Hawaiian(Pizza):
"""Класс Гавайской пиццы"""

def __init__(self, size: str = "L"):
self.name = "Hawaiian 🍍"
self.extra_ingredients = ["chicken", "pineapples"]
super().__init__(size, self.name, self.extra_ingredients)
46 changes: 46 additions & 0 deletions pizza_project/services.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import random
from typing import Callable
from pizza import Pizza, Margherita, Pepperoni, Hawaiian


def log(params: str) -> Callable:
"""
Декоратор логирует время исполнения функции.
Принимает шаблон и выводит случайное значение.
:param params: str
:return: Callable
"""

def decorator(func: Callable) -> Callable:
nonlocal params
if not isinstance(params, str):
params = params.__name__ + ' - {}c!'
print(params.format(random.randint(1, 10)))

def wrapper(*args, **kwargs):
print(params.format(random.randint(1, 10)))
return func(*args, **kwargs)

return wrapper

return decorator


@log

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Почему здесь ничего не пишется фраза с картинкой?

def bake(pizza: Pizza):
"""Готовит пиццу"""


@log('🛵 доставили за {} минут!')
def deliver(pizza: Pizza):
"""Доставляет пиццу"""


@log('🏠 забрали за {} минут!')
def pickup(pizza: Pizza):
"""Самовывоз"""


if __name__ == '__main__':
bake(Margherita())
deliver(Hawaiian())
124 changes: 124 additions & 0 deletions pizza_project/testing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import pytest
import random
from pizza import Pizza, Margherita, Pepperoni, Hawaiian
from services import bake, deliver, pickup
from cli import order, menu
from click.testing import CliRunner


def test_equality():
"""
Проверка пицц на равенство/
проверка корректность работы магического метода __eq__
:return: None
"""
assert Hawaiian() == Hawaiian()
assert Hawaiian(size='XL') != Hawaiian(size='L')
assert Hawaiian() != Pepperoni()


def test_pizza_dict():
"""
Проверка на корректность работы функции dict
:return: None
"""
assert Pizza().dict() == {None: 'tomato sauce, mozzarella'}
assert Margherita().dict() == {'Margherita 🧀': 'tomato sauce, mozzarella, tomatoes'}
assert Pepperoni().dict() == {'Pepperoni 🍕': 'tomato sauce, mozzarella, pepperoni'}
assert Hawaiian().dict() == {'Hawaiian 🍍': 'tomato sauce, mozzarella, chicken, pineapples'}
assert Margherita().__class__.__name__ != str(*Hawaiian().dict().keys())


def test_size_exceptions():
"""
Провека корректность вызова исключений при некорректном вводе размера пиццы
:return: None
"""
with pytest.raises(ValueError):
Pizza(size='l')
with pytest.raises(ValueError):
Pizza(size=30)


def test_with_decorator():
"""
Проверка выходов функций услуг
:return: None
"""
assert deliver(Margherita()) is None
assert pickup(Margherita()) is None


def test_bake(capsys):
"""
Проверка работы функции bake вместе с декоратором
:return: None
"""
random.seed(42)
bake(Margherita())
out = capsys.readouterr().out.split("\n")
assert out[0] == 'bake - 2c!'


def test_deliver(capsys):
"""
Проверка работы функции deliver вместе с декоратором
:return: None
"""
result = deliver(Margherita())
out, err = capsys.readouterr().out.split("\n")
assert result is None
assert out.startswith("🛵 доставили за")


def test_pickup(capsys):
"""
Проверка работы функции pickup вместе с декоратором
:return: None
"""
result = pickup(Margherita())
out, err = capsys.readouterr().out.split("\n")
assert result is None
assert out.startswith("🏠 забрали за")


def test_menu():
"""
Проверка корректности выводимого меню
:return: None
"""
runner = CliRunner()
result = runner.invoke(menu)
assert result.output == "- Margherita 🧀: tomato sauce, mozzarella, tomatoes\n" \
"- Pepperoni 🍕: tomato sauce, mozzarella, pepperoni\n" \
"- Hawaiian 🍍: tomato sauce, mozzarella, chicken, pineapples\n"


def test_invalid_order():
"""
Проверка работы терминальных функций при некорректном наименовании пиццы
:return: None
"""
runner = CliRunner()
result = runner.invoke(order, ["margarita"])
assert result.output.strip() == ''


def test_order_no_delivery_flag():
"""
Проверка работы терминальных функций заказа без использования флага доставки
:return: None
"""
runner = CliRunner()
result = runner.invoke(order, ["pepperoni"])
assert " забрали за" in result.output.strip()


def test_order_no_delivery_flag():
"""
Проверка работы терминальных функций заказа с использованием флага доставки
:return: None
"""
runner = CliRunner()
result = runner.invoke(order, ["pepperoni", "--delivery"])
assert " доставили за" in result.output.strip()