diff --git a/.coverage b/.coverage new file mode 100644 index 000000000..6618185f0 Binary files /dev/null and b/.coverage differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..1eb5137c4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +venv/ +.venv/ +env/ +ENV/ +env.bak/ +venv.bak/ +__pycache__/ +*.pyc +*.pyo +*.pyd +.pytest_cache/ +.mypy_cache/ +.ruff_cache/ +allure-results/ +allure-report/ +.logs/ +*.log +.idea/ +.vscode/ +*.swp +*.swo +*~ \ No newline at end of file diff --git a/README.md b/README.md index 272081708..99da38412 100644 --- a/README.md +++ b/README.md @@ -8,17 +8,8 @@ Процент покрытия 100% (отчет: `htmlcov/index.html`) -### Структура проекта - -- `praktikum` - пакет, содержащий код программы -- `tests` - пакет, содержащий тесты, разделенные по классам. Например, `bun_test.py`, `burger_test.py` и т.д. - ### Запуск автотестов -**Установка зависимостей** - -> `$ pip install -r requirements.txt` - **Запуск автотестов и создание HTML-отчета о покрытии** -> `$ pytest --cov=praktikum --cov-report=html` +> `pytest --cov=Diplom_1.burger --cov-report=html --cov-report=term` diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 000000000..a27390039 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,29 @@ +import sys +from unittest.mock import MagicMock, Mock + +sys.modules['praktikum'] = MagicMock() +sys.modules['praktikum.bun'] = MagicMock() +sys.modules['praktikum.ingredient'] = MagicMock() +sys.modules['praktikum.bun'].Bun = Mock() +sys.modules['praktikum.ingredient'].Ingredient = Mock() + +from Diplom_1.burger import Burger +from .mocks import create_mock_bun, create_mock_ingredient + +import pytest + +@pytest.fixture +def burger(): + return Burger() + +@pytest.fixture +def mock_bun(): + return create_mock_bun() + +@pytest.fixture +def mock_sauce(): + return create_mock_ingredient(ingredient_type="sauce", name="hot sauce", price=50) + +@pytest.fixture +def mock_filling(): + return create_mock_ingredient(ingredient_type="filling", name="cheese", price=70) diff --git a/tests/mocks.py b/tests/mocks.py new file mode 100644 index 000000000..829f2b6c9 --- /dev/null +++ b/tests/mocks.py @@ -0,0 +1,14 @@ +from unittest.mock import Mock + +def create_mock_bun(name="black bun", price=100): + bun = Mock() + bun.get_name.return_value = name + bun.get_price.return_value = price + return bun + +def create_mock_ingredient(ingredient_type="sauce", name="hot sauce", price=50): + ing = Mock() + ing.get_type.return_value = ingredient_type + ing.get_name.return_value = name + ing.get_price.return_value = price + return ing diff --git a/tests/test_burger.py b/tests/test_burger.py new file mode 100644 index 000000000..985b39d36 --- /dev/null +++ b/tests/test_burger.py @@ -0,0 +1,130 @@ +import pytest +from unittest.mock import Mock + +class TestBurger: + def test_set_buns(self, burger, mock_bun): + burger.set_buns(mock_bun) + assert burger.bun == mock_bun + + def test_add_ingredient(self, burger): + ingredient = Mock() + burger.add_ingredient(ingredient) + assert len(burger.ingredients) == 1 + assert burger.ingredients[0] == ingredient + + def test_remove_ingredient_first(self, burger): + ing1 = Mock() + ing2 = Mock() + burger.add_ingredient(ing1) + burger.add_ingredient(ing2) + burger.remove_ingredient(0) + assert len(burger.ingredients) == 1 + assert burger.ingredients[0] == ing2 + + def test_remove_ingredient_last(self, burger): + ing1 = Mock() + ing2 = Mock() + burger.add_ingredient(ing1) + burger.add_ingredient(ing2) + burger.remove_ingredient(1) + assert len(burger.ingredients) == 1 + assert burger.ingredients[0] == ing1 + + def test_remove_ingredient_single(self, burger): + ing = Mock() + burger.add_ingredient(ing) + burger.remove_ingredient(0) + assert len(burger.ingredients) == 0 + + def test_remove_ingredient_invalid_index(self, burger): + ing = Mock() + burger.add_ingredient(ing) + with pytest.raises(IndexError): + burger.remove_ingredient(1) + + def test_move_ingredient_same_index(self, burger): + ing1 = Mock() + ing2 = Mock() + burger.add_ingredient(ing1) + burger.add_ingredient(ing2) + burger.move_ingredient(0, 0) + assert burger.ingredients[0] == ing1 + assert burger.ingredients[1] == ing2 + + def test_move_ingredient(self, burger): + ing1 = Mock() + ing2 = Mock() + burger.add_ingredient(ing1) + burger.add_ingredient(ing2) + burger.move_ingredient(0, 1) + assert burger.ingredients[0] == ing2 + assert burger.ingredients[1] == ing1 + + def test_move_ingredient_from_end_to_start(self, burger): + ing1 = Mock() + ing2 = Mock() + burger.add_ingredient(ing1) + burger.add_ingredient(ing2) + burger.move_ingredient(1, 0) + assert burger.ingredients[0] == ing2 + assert burger.ingredients[1] == ing1 + + def test_get_price_only_bun(self, burger, mock_bun): + burger.set_buns(mock_bun) + expected_price = mock_bun.get_price() * 2 + assert burger.get_price() == expected_price + + def test_get_price_no_bun(self, burger): + ing = Mock() + burger.add_ingredient(ing) + with pytest.raises(AttributeError): + burger.get_price() + + def test_get_receipt_no_bun(self, burger): + ing = Mock() + burger.add_ingredient(ing) + with pytest.raises(AttributeError): + burger.get_receipt() + + @pytest.mark.parametrize("sauce_count, filling_count", [ + (0, 0), + (1, 0), + (1, 1) + ]) + def test_get_receipt(self, burger, mock_bun, mock_sauce, mock_filling, sauce_count, filling_count): + burger.set_buns(mock_bun) + ingredients = [] + + for _ in range(sauce_count): + burger.add_ingredient(mock_sauce) + ingredients.append(mock_sauce) + for _ in range(filling_count): + burger.add_ingredient(mock_filling) + ingredients.append(mock_filling) + + bun_price = mock_bun.get_price() + total_price = bun_price * 2 + sum(ing.get_price() for ing in ingredients) + + lines = [f"(==== {mock_bun.get_name()} ====)"] + for ing in burger.ingredients: + lines.append(f"= {ing.get_type()} {ing.get_name()} =") + lines.append(f"(==== {mock_bun.get_name()} ====)") + lines.append("") + lines.append(f"Price: {total_price}") + expected = "\n".join(lines) + + assert burger.get_receipt() == expected + + def test_get_price_without_bun_and_ingredients(self, burger): + with pytest.raises(AttributeError): + burger.get_price() + + def test_move_ingredient_invalid_index(self, burger): + ing = Mock() + burger.add_ingredient(ing) + with pytest.raises(IndexError): + burger.move_ingredient(1, 0) + with pytest.raises(IndexError): + burger.move_ingredient(-2, 0) + burger.move_ingredient(0, 5) + \ No newline at end of file