diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..320d4aa86 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +__pycache__/ +*.py[cod] +.coverage +.pytest_cache/ +venv/ +.env \ 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/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/tests/__pycache__/conftest.cpython-314-pytest-9.0.2.pyc b/tests/__pycache__/conftest.cpython-314-pytest-9.0.2.pyc new file mode 100644 index 000000000..c1926c885 Binary files /dev/null and b/tests/__pycache__/conftest.cpython-314-pytest-9.0.2.pyc differ diff --git a/tests/__pycache__/test_bun.cpython-314-pytest-9.0.2.pyc b/tests/__pycache__/test_bun.cpython-314-pytest-9.0.2.pyc new file mode 100644 index 000000000..a4cbc912f Binary files /dev/null and b/tests/__pycache__/test_bun.cpython-314-pytest-9.0.2.pyc differ diff --git a/tests/__pycache__/test_ingredient.cpython-314-pytest-9.0.2.pyc b/tests/__pycache__/test_ingredient.cpython-314-pytest-9.0.2.pyc new file mode 100644 index 000000000..43c8c12b8 Binary files /dev/null and b/tests/__pycache__/test_ingredient.cpython-314-pytest-9.0.2.pyc differ diff --git a/tests/burger_tests/__init__.py b/tests/burger_tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/burger_tests/__pycache__/__init__.cpython-314.pyc b/tests/burger_tests/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 000000000..297564114 Binary files /dev/null and b/tests/burger_tests/__pycache__/__init__.cpython-314.pyc differ diff --git a/tests/burger_tests/__pycache__/test_ingredients_management.cpython-314-pytest-9.0.2.pyc b/tests/burger_tests/__pycache__/test_ingredients_management.cpython-314-pytest-9.0.2.pyc new file mode 100644 index 000000000..ab3045fee Binary files /dev/null and b/tests/burger_tests/__pycache__/test_ingredients_management.cpython-314-pytest-9.0.2.pyc differ diff --git a/tests/burger_tests/__pycache__/test_initialization.cpython-314-pytest-9.0.2.pyc b/tests/burger_tests/__pycache__/test_initialization.cpython-314-pytest-9.0.2.pyc new file mode 100644 index 000000000..da76ec97d Binary files /dev/null and b/tests/burger_tests/__pycache__/test_initialization.cpython-314-pytest-9.0.2.pyc differ diff --git a/tests/burger_tests/__pycache__/test_price.cpython-314-pytest-9.0.2.pyc b/tests/burger_tests/__pycache__/test_price.cpython-314-pytest-9.0.2.pyc new file mode 100644 index 000000000..8c194af07 Binary files /dev/null and b/tests/burger_tests/__pycache__/test_price.cpython-314-pytest-9.0.2.pyc differ diff --git a/tests/burger_tests/__pycache__/test_receipt.cpython-314-pytest-9.0.2.pyc b/tests/burger_tests/__pycache__/test_receipt.cpython-314-pytest-9.0.2.pyc new file mode 100644 index 000000000..68cdb7a6f Binary files /dev/null and b/tests/burger_tests/__pycache__/test_receipt.cpython-314-pytest-9.0.2.pyc differ diff --git a/tests/burger_tests/test_ingredients_management.py b/tests/burger_tests/test_ingredients_management.py new file mode 100644 index 000000000..be2ab81b7 --- /dev/null +++ b/tests/burger_tests/test_ingredients_management.py @@ -0,0 +1,65 @@ +import pytest +from unittest.mock import Mock +from burger import Burger +from ingredient import Ingredient + +class TestBurgerIngredientsManagement: + + def setup_method(self): + self.burger = Burger() + self.mock_ingredient1 = Mock(spec=Ingredient) + self.mock_ingredient2 = Mock(spec=Ingredient) + + def test_add_ingredient_increases_length(self): + self.burger.add_ingredient(self.mock_ingredient1) + assert len(self.burger.ingredients) == 1 + + def test_add_ingredient_adds_correct_ingredient(self): + self.burger.add_ingredient(self.mock_ingredient1) + assert self.burger.ingredients[0] == self.mock_ingredient1 + + def test_add_multiple_ingredients_increases_length(self): + self.burger.add_ingredient(self.mock_ingredient1) + self.burger.add_ingredient(self.mock_ingredient2) + assert len(self.burger.ingredients) == 2 + + def test_remove_ingredient_decreases_length(self): + self.burger.add_ingredient(self.mock_ingredient1) + self.burger.add_ingredient(self.mock_ingredient2) + self.burger.remove_ingredient(0) + assert len(self.burger.ingredients) == 1 + + def test_remove_ingredient_removes_correct_element(self): + self.burger.add_ingredient(self.mock_ingredient1) + self.burger.add_ingredient(self.mock_ingredient2) + self.burger.remove_ingredient(0) + assert self.burger.ingredients[0] == self.mock_ingredient2 + + def test_remove_ingredient_invalid_index_raises_error(self): + self.burger.add_ingredient(self.mock_ingredient1) + with pytest.raises(IndexError): + self.burger.remove_ingredient(5) + + def test_move_ingredient_changes_position(self): + self.burger.add_ingredient(self.mock_ingredient1) + self.burger.add_ingredient(self.mock_ingredient2) + self.burger.move_ingredient(0, 1) + assert self.burger.ingredients[0] == self.mock_ingredient2 + + def test_move_ingredient_places_element_at_new_index(self): + self.burger.add_ingredient(self.mock_ingredient1) + self.burger.add_ingredient(self.mock_ingredient2) + self.burger.move_ingredient(0, 1) + assert self.burger.ingredients[1] == self.mock_ingredient1 + + def test_move_ingredient_to_same_position_keeps_first_element(self): + self.burger.add_ingredient(self.mock_ingredient1) + self.burger.add_ingredient(self.mock_ingredient2) + self.burger.move_ingredient(0, 0) + assert self.burger.ingredients[0] == self.mock_ingredient1 + + def test_move_ingredient_to_same_position_keeps_second_element(self): + self.burger.add_ingredient(self.mock_ingredient1) + self.burger.add_ingredient(self.mock_ingredient2) + self.burger.move_ingredient(0, 0) + assert self.burger.ingredients[1] == self.mock_ingredient2 \ No newline at end of file diff --git a/tests/burger_tests/test_initialization.py b/tests/burger_tests/test_initialization.py new file mode 100644 index 000000000..cbb703f89 --- /dev/null +++ b/tests/burger_tests/test_initialization.py @@ -0,0 +1,20 @@ +import pytest +from unittest.mock import Mock +from burger import Burger +from bun import Bun + +class TestBurgerInitialization: + + def setup_method(self): + self.burger = Burger() + + def test_initial_burger_has_no_bun(self): + assert self.burger.bun is None + + def test_initial_burger_has_empty_ingredients(self): + assert self.burger.ingredients == [] + + def test_set_buns_sets_bun_correctly(self): + mock_bun = Mock(spec=Bun) + self.burger.set_buns(mock_bun) + assert self.burger.bun == mock_bun \ No newline at end of file diff --git a/tests/burger_tests/test_price.py b/tests/burger_tests/test_price.py new file mode 100644 index 000000000..213fa0ad0 --- /dev/null +++ b/tests/burger_tests/test_price.py @@ -0,0 +1,48 @@ +import pytest +from unittest.mock import Mock +from burger import Burger +from bun import Bun +from ingredient import Ingredient +from ingredient_types import INGREDIENT_TYPE_SAUCE, INGREDIENT_TYPE_FILLING + +class TestBurgerPrice: + + def setup_method(self): + self.burger = Burger() + self.mock_bun = Mock(spec=Bun) + self.mock_bun.get_price.return_value = 100 + + self.mock_ingredient1 = Mock(spec=Ingredient) + self.mock_ingredient1.get_price.return_value = 50 + + self.mock_ingredient2 = Mock(spec=Ingredient) + self.mock_ingredient2.get_price.return_value = 150 + + def test_get_price_with_bun_only_returns_double_bun_price(self): + self.burger.set_buns(self.mock_bun) + assert self.burger.get_price() == 200 + + def test_get_price_with_bun_and_ingredients_sums_correctly(self): + self.burger.set_buns(self.mock_bun) + self.burger.add_ingredient(self.mock_ingredient1) + self.burger.add_ingredient(self.mock_ingredient2) + assert self.burger.get_price() == 400 + + @pytest.mark.parametrize("bun_price, ingredient_prices, expected_total", [ + (100, [50, 75], 325), + (200, [100], 500), + (50, [25, 25, 25], 175), + (0, [0, 0], 0), + ]) + def test_get_price_parametrized_returns_correct_total(self, bun_price, ingredient_prices, expected_total): + mock_bun = Mock(spec=Bun) + mock_bun.get_price.return_value = bun_price + + self.burger.set_buns(mock_bun) + + for price in ingredient_prices: + mock_ingredient = Mock(spec=Ingredient) + mock_ingredient.get_price.return_value = price + self.burger.add_ingredient(mock_ingredient) + + assert self.burger.get_price() == expected_total \ No newline at end of file diff --git a/tests/burger_tests/test_receipt.py b/tests/burger_tests/test_receipt.py new file mode 100644 index 000000000..872356653 --- /dev/null +++ b/tests/burger_tests/test_receipt.py @@ -0,0 +1,51 @@ +import pytest +from unittest.mock import Mock, patch +from burger import Burger +from bun import Bun +from ingredient import Ingredient +from ingredient_types import INGREDIENT_TYPE_SAUCE + +class TestBurgerReceipt: + + def setup_method(self): + self.burger = Burger() + self.mock_bun = Mock(spec=Bun) + self.mock_bun.get_name.return_value = "black bun" + + self.mock_ingredient = Mock(spec=Ingredient) + self.mock_ingredient.get_name.return_value = "hot sauce" + self.mock_ingredient.get_type.return_value = INGREDIENT_TYPE_SAUCE + + @patch('burger.Burger.get_price') + def test_get_receipt_contains_bun_name(self, mock_get_price): + mock_get_price.return_value = 250 + self.burger.set_buns(self.mock_bun) + self.burger.add_ingredient(self.mock_ingredient) + + receipt = self.burger.get_receipt() + + assert "(==== black bun ====)" in receipt + + @patch('burger.Burger.get_price') + def test_get_receipt_contains_ingredient(self, mock_get_price): + mock_get_price.return_value = 250 + self.burger.set_buns(self.mock_bun) + self.burger.add_ingredient(self.mock_ingredient) + + receipt = self.burger.get_receipt() + + assert "= sauce hot sauce =" in receipt + + @patch('burger.Burger.get_price') + def test_get_receipt_contains_price(self, mock_get_price): + mock_get_price.return_value = 250 + self.burger.set_buns(self.mock_bun) + self.burger.add_ingredient(self.mock_ingredient) + + receipt = self.burger.get_receipt() + + assert "Price: 250" in receipt + + def test_get_receipt_without_bun_raises_error(self): + with pytest.raises(AttributeError): + self.burger.get_receipt() \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 000000000..102295e96 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,4 @@ +import sys +import os + +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) \ No newline at end of file diff --git a/tests/database_tests/__init__.py b/tests/database_tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/database_tests/__pycache__/__init__.cpython-314.pyc b/tests/database_tests/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 000000000..2cb088520 Binary files /dev/null and b/tests/database_tests/__pycache__/__init__.cpython-314.pyc differ diff --git a/tests/database_tests/__pycache__/test_available_buns.cpython-314-pytest-9.0.2.pyc b/tests/database_tests/__pycache__/test_available_buns.cpython-314-pytest-9.0.2.pyc new file mode 100644 index 000000000..094a1359a Binary files /dev/null and b/tests/database_tests/__pycache__/test_available_buns.cpython-314-pytest-9.0.2.pyc differ diff --git a/tests/database_tests/__pycache__/test_available_ingredients.cpython-314-pytest-9.0.2.pyc b/tests/database_tests/__pycache__/test_available_ingredients.cpython-314-pytest-9.0.2.pyc new file mode 100644 index 000000000..9c26971cb Binary files /dev/null and b/tests/database_tests/__pycache__/test_available_ingredients.cpython-314-pytest-9.0.2.pyc differ diff --git a/tests/database_tests/__pycache__/test_content.cpython-314-pytest-9.0.2.pyc b/tests/database_tests/__pycache__/test_content.cpython-314-pytest-9.0.2.pyc new file mode 100644 index 000000000..37a3f2195 Binary files /dev/null and b/tests/database_tests/__pycache__/test_content.cpython-314-pytest-9.0.2.pyc differ diff --git a/tests/database_tests/__pycache__/test_initialization.cpython-314-pytest-9.0.2.pyc b/tests/database_tests/__pycache__/test_initialization.cpython-314-pytest-9.0.2.pyc new file mode 100644 index 000000000..8823bbbb4 Binary files /dev/null and b/tests/database_tests/__pycache__/test_initialization.cpython-314-pytest-9.0.2.pyc differ diff --git a/tests/database_tests/test_available_buns.py b/tests/database_tests/test_available_buns.py new file mode 100644 index 000000000..c54a9883b --- /dev/null +++ b/tests/database_tests/test_available_buns.py @@ -0,0 +1,39 @@ +from database import Database + +class TestDatabaseAvailableBuns: + + def setup_method(self): + self.database = Database() + + def test_available_buns_returns_three_buns(self): + buns = self.database.available_buns() + assert len(buns) == 3 + + def test_available_buns_first_bun_is_black_bun(self): + buns = self.database.available_buns() + assert buns[0].get_name() == "black bun" + + def test_available_buns_first_bun_price_is_100(self): + buns = self.database.available_buns() + assert buns[0].get_price() == 100 + + def test_available_buns_second_bun_is_white_bun(self): + buns = self.database.available_buns() + assert buns[1].get_name() == "white bun" + + def test_available_buns_second_bun_price_is_200(self): + buns = self.database.available_buns() + assert buns[1].get_price() == 200 + + def test_available_buns_third_bun_is_red_bun(self): + buns = self.database.available_buns() + assert buns[2].get_name() == "red bun" + + def test_available_buns_third_bun_price_is_300(self): + buns = self.database.available_buns() + assert buns[2].get_price() == 300 + + def test_available_buns_returns_same_reference(self): + buns1 = self.database.available_buns() + buns2 = self.database.available_buns() + assert buns1 is buns2 \ No newline at end of file diff --git a/tests/database_tests/test_available_ingredients.py b/tests/database_tests/test_available_ingredients.py new file mode 100644 index 000000000..dbd121c3f --- /dev/null +++ b/tests/database_tests/test_available_ingredients.py @@ -0,0 +1,26 @@ +from database import Database +from ingredient_types import INGREDIENT_TYPE_SAUCE, INGREDIENT_TYPE_FILLING + +class TestDatabaseAvailableIngredients: + + def setup_method(self): + self.database = Database() + + def test_available_ingredients_returns_six_ingredients(self): + ingredients = self.database.available_ingredients() + assert len(ingredients) == 6 + + def test_available_ingredients_contains_three_sauces(self): + ingredients = self.database.available_ingredients() + sauces = [ing for ing in ingredients if ing.get_type() == INGREDIENT_TYPE_SAUCE] + assert len(sauces) == 3 + + def test_available_ingredients_contains_three_fillings(self): + ingredients = self.database.available_ingredients() + fillings = [ing for ing in ingredients if ing.get_type() == INGREDIENT_TYPE_FILLING] + assert len(fillings) == 3 + + def test_available_ingredients_returns_same_reference(self): + ingredients1 = self.database.available_ingredients() + ingredients2 = self.database.available_ingredients() + assert ingredients1 is ingredients2 \ No newline at end of file diff --git a/tests/database_tests/test_content.py b/tests/database_tests/test_content.py new file mode 100644 index 000000000..7400f0642 --- /dev/null +++ b/tests/database_tests/test_content.py @@ -0,0 +1,42 @@ +import pytest +from database import Database +from ingredient_types import INGREDIENT_TYPE_SAUCE, INGREDIENT_TYPE_FILLING + +class TestDatabaseContent: + + def setup_method(self): + self.database = Database() + + @pytest.mark.parametrize("bun_index, expected_name", [ + (0, "black bun"), (1, "white bun"), (2, "red bun"), + ]) + def test_bun_has_correct_name(self, bun_index, expected_name): + assert self.database.buns[bun_index].get_name() == expected_name + + @pytest.mark.parametrize("bun_index, expected_price", [ + (0, 100), (1, 200), (2, 300), + ]) + def test_bun_has_correct_price(self, bun_index, expected_price): + assert self.database.buns[bun_index].get_price() == expected_price + + @pytest.mark.parametrize("ingredient_index, expected_type", [ + (0, INGREDIENT_TYPE_SAUCE), (1, INGREDIENT_TYPE_SAUCE), + (2, INGREDIENT_TYPE_SAUCE), (3, INGREDIENT_TYPE_FILLING), + (4, INGREDIENT_TYPE_FILLING), (5, INGREDIENT_TYPE_FILLING), + ]) + def test_ingredient_has_correct_type(self, ingredient_index, expected_type): + assert self.database.ingredients[ingredient_index].get_type() == expected_type + + @pytest.mark.parametrize("ingredient_index, expected_name", [ + (0, "hot sauce"), (1, "sour cream"), (2, "chili sauce"), + (3, "cutlet"), (4, "dinosaur"), (5, "sausage"), + ]) + def test_ingredient_has_correct_name(self, ingredient_index, expected_name): + assert self.database.ingredients[ingredient_index].get_name() == expected_name + + @pytest.mark.parametrize("ingredient_index, expected_price", [ + (0, 100), (1, 200), (2, 300), + (3, 100), (4, 200), (5, 300), + ]) + def test_ingredient_has_correct_price(self, ingredient_index, expected_price): + assert self.database.ingredients[ingredient_index].get_price() == expected_price \ No newline at end of file diff --git a/tests/database_tests/test_initialization.py b/tests/database_tests/test_initialization.py new file mode 100644 index 000000000..7c70d4740 --- /dev/null +++ b/tests/database_tests/test_initialization.py @@ -0,0 +1,20 @@ +from database import Database +from bun import Bun +from ingredient import Ingredient + +class TestDatabaseInitialization: + + def setup_method(self): + self.database = Database() + + def test_initialization_creates_three_buns(self): + assert len(self.database.buns) == 3 + + def test_initialization_buns_are_bun_instances(self): + assert all(isinstance(bun, Bun) for bun in self.database.buns) + + def test_initialization_creates_six_ingredients(self): + assert len(self.database.ingredients) == 6 + + def test_initialization_ingredients_are_ingredient_instances(self): + assert all(isinstance(ing, Ingredient) for ing in self.database.ingredients) \ No newline at end of file diff --git a/tests/test_bun.py b/tests/test_bun.py new file mode 100644 index 000000000..8476ffa32 --- /dev/null +++ b/tests/test_bun.py @@ -0,0 +1,39 @@ +import pytest +from bun import Bun + +class TestBun: + + @pytest.mark.parametrize("name, price", [ + ("black bun", 100), + ("white bun", 200), + ("red bun", 300), + ("", 0), + ("special bun", 99.99), + ]) + def test_bun_creation_returns_correct_name(self, name, price): + bun = Bun(name, price) + assert bun.get_name() == name + + @pytest.mark.parametrize("name, price", [ + ("black bun", 100), + ("white bun", 200), + ("red bun", 300), + ("", 0), + ("special bun", 99.99), + ]) + def test_bun_creation_returns_correct_price(self, name, price): + bun = Bun(name, price) + assert bun.get_price() == price + + def test_bun_get_name_returns_correct_value(self): + bun = Bun("black bun", 100) + assert bun.get_name() == "black bun" + + def test_bun_get_price_returns_correct_value(self): + bun = Bun("white bun", 200) + assert bun.get_price() == 200 + + @pytest.mark.parametrize("price", [0, 0.01, 50, 100.5, 999.99]) + def test_bun_price_accepts_different_values(self, price): + bun = Bun("test bun", price) + assert bun.get_price() == price \ No newline at end of file diff --git a/tests/test_ingredient.py b/tests/test_ingredient.py new file mode 100644 index 000000000..94d45db5f --- /dev/null +++ b/tests/test_ingredient.py @@ -0,0 +1,47 @@ +import pytest +from ingredient import Ingredient +from ingredient_types import INGREDIENT_TYPE_SAUCE, INGREDIENT_TYPE_FILLING + +class TestIngredient: + + @pytest.mark.parametrize("ingredient_type, name, price", [ + (INGREDIENT_TYPE_SAUCE, "hot sauce", 100), + (INGREDIENT_TYPE_SAUCE, "sour cream", 200), + (INGREDIENT_TYPE_FILLING, "cutlet", 100), + (INGREDIENT_TYPE_FILLING, "dinosaur", 200), + ]) + def test_ingredient_creation_returns_correct_type(self, ingredient_type, name, price): + ingredient = Ingredient(ingredient_type, name, price) + assert ingredient.get_type() == ingredient_type + + @pytest.mark.parametrize("ingredient_type, name, price", [ + (INGREDIENT_TYPE_SAUCE, "hot sauce", 100), + (INGREDIENT_TYPE_SAUCE, "sour cream", 200), + (INGREDIENT_TYPE_FILLING, "cutlet", 100), + (INGREDIENT_TYPE_FILLING, "dinosaur", 200), + ]) + def test_ingredient_creation_returns_correct_name(self, ingredient_type, name, price): + ingredient = Ingredient(ingredient_type, name, price) + assert ingredient.get_name() == name + + @pytest.mark.parametrize("ingredient_type, name, price", [ + (INGREDIENT_TYPE_SAUCE, "hot sauce", 100), + (INGREDIENT_TYPE_SAUCE, "sour cream", 200), + (INGREDIENT_TYPE_FILLING, "cutlet", 100), + (INGREDIENT_TYPE_FILLING, "dinosaur", 200), + ]) + def test_ingredient_creation_returns_correct_price(self, ingredient_type, name, price): + ingredient = Ingredient(ingredient_type, name, price) + assert ingredient.get_price() == price + + def test_ingredient_get_price_returns_correct_value(self): + ingredient = Ingredient(INGREDIENT_TYPE_SAUCE, "hot sauce", 150) + assert ingredient.get_price() == 150 + + def test_ingredient_get_name_returns_correct_value(self): + ingredient = Ingredient(INGREDIENT_TYPE_FILLING, "cutlet", 100) + assert ingredient.get_name() == "cutlet" + + def test_ingredient_get_type_returns_correct_value(self): + ingredient = Ingredient(INGREDIENT_TYPE_SAUCE, "chili sauce", 300) + assert ingredient.get_type() == INGREDIENT_TYPE_SAUCE \ No newline at end of file