diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..7492c1589 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.coverage +__pycache__ +.pytest_cache + diff --git a/README.md b/README.md index 272081708..825944828 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,2 @@ -## Задание 1: Юнит-тесты +# Task_1 # -### Автотесты для проверки программы, которая помогает заказать бургер в Stellar Burgers - -### Реализованные сценарии - -Созданы юнит-тесты, покрывающие классы `Bun`, `Burger`, `Ingredient`, `Database` - -Процент покрытия 100% (отчет: `htmlcov/index.html`) - -### Структура проекта - -- `praktikum` - пакет, содержащий код программы -- `tests` - пакет, содержащий тесты, разделенные по классам. Например, `bun_test.py`, `burger_test.py` и т.д. - -### Запуск автотестов - -**Установка зависимостей** - -> `$ pip install -r requirements.txt` - -**Запуск автотестов и создание HTML-отчета о покрытии** - -> `$ pytest --cov=praktikum --cov-report=html` diff --git a/__init__.py b/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/conftest.py b/conftest.py new file mode 100644 index 000000000..68a398609 --- /dev/null +++ b/conftest.py @@ -0,0 +1,21 @@ +import pytest +from unittest.mock import Mock +from praktikum.bun import Bun +from praktikum.ingredient import Ingredient +from praktikum.ingredient_types import INGREDIENT_TYPE_FILLING + + +@pytest.fixture +def mock_bun(): + bun = Mock(spec=Bun) + bun.get_name.return_value = "mock bun" + bun.get_price.return_value = 50 + return bun + +@pytest.fixture +def mock_ingredient(): + ing = Mock(spec=Ingredient) + ing.get_name.return_value = "mock ingredient" + ing.get_price.return_value = 20 + ing.get_type.return_value = INGREDIENT_TYPE_FILLING + return ing \ No newline at end of file diff --git a/data.py b/data.py new file mode 100644 index 000000000..6a23722a7 --- /dev/null +++ b/data.py @@ -0,0 +1,19 @@ +from praktikum.ingredient_types import INGREDIENT_TYPE_SAUCE, INGREDIENT_TYPE_FILLING + +BunData = [ + ('black bun', 100), + ('white bun', 200), + ('red bun', 300)] + +IngredientData = [ + ("hot sauce", INGREDIENT_TYPE_SAUCE, 100), + ("sour cream", INGREDIENT_TYPE_SAUCE, 200), + ("chili sauce", INGREDIENT_TYPE_SAUCE, 300), + ("cutlet", INGREDIENT_TYPE_FILLING, 100), + ("dinosaur", INGREDIENT_TYPE_FILLING, 200), + ("sausage", INGREDIENT_TYPE_FILLING, 300)] + + + + + diff --git a/index.html b/index.html new file mode 100644 index 000000000..b981aef86 --- /dev/null +++ b/index.html @@ -0,0 +1,144 @@ + + + + + Coverage report + + + + + +
+
+

Coverage report: + 100% +

+ +
+ +
+ + +
+
+

+ Files + Functions + Classes +

+

+ coverage.py v7.12.0, + created at 2026-01-06 16:27 +0300 +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
File statementsmissingexcluded coverage
tests \ test_bun.py 1700 100%
tests \ test_burger.py 5800 100%
tests \ test_database.py 3400 100%
tests \ test_ingredient.py 1600 100%
Total 12500 100%
+

+ No items found using the specified filter. +

+
+ + + 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 99% rename from burger.py rename to praktikum/burger.py index 2b3b6a88b..4b195996f 100644 --- a/burger.py +++ b/praktikum/burger.py @@ -3,7 +3,6 @@ from praktikum.bun import Bun from praktikum.ingredient import Ingredient - class Burger: """ Модель бургера. 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..2a2067c24 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ + +pytest 9.0.1 +pytest-cov 7.0.0 diff --git a/tests/test_bun.py b/tests/test_bun.py new file mode 100644 index 000000000..b477e00e8 --- /dev/null +++ b/tests/test_bun.py @@ -0,0 +1,22 @@ +import pytest +from praktikum.bun import Bun +from data import BunData + + +class TestBun: + @pytest.mark.parametrize('name, price', BunData) + def test_bun_constructor(self, name, price): + bun = Bun(name, price) + + assert bun.name == name + assert bun.price == price + + @pytest.mark.parametrize('name, price', BunData) + def test_get_name(self, name, price): + bun = Bun(name, price) + assert bun.get_name() == name + + @pytest.mark.parametrize('name, price', BunData) + def test_get_price(self, name, price): + bun = Bun(name, price) + assert bun.get_price() == price diff --git a/tests/test_burger.py b/tests/test_burger.py new file mode 100644 index 000000000..fbdcad774 --- /dev/null +++ b/tests/test_burger.py @@ -0,0 +1,69 @@ +import pytest +from unittest.mock import Mock +from praktikum.bun import Bun +from praktikum.burger import Burger +from praktikum.ingredient import Ingredient +from data import BunData, IngredientData + + +class TestBurger: + + def test_burger_initial_state(self): + burger = Burger() + assert burger.bun is None + assert burger.ingredients == [] + + @pytest.mark.parametrize("bun_name, bun_price", BunData) + def test_set_bun(self, bun_name, bun_price): + burger = Burger() + mock_bun = Mock(spec=Bun) + mock_bun.get_name.return_value = bun_name + mock_bun.get_price.return_value = bun_price + burger.set_buns(mock_bun) + assert burger.bun == mock_bun + assert burger.bun.get_name() == bun_name + assert burger.bun.get_price() == bun_price + + @pytest.mark.parametrize("name, type_i, price", IngredientData) + def test_add_ingredient(self, name, type_i, price): + burger = Burger() + mock_ingredient = Mock(spec=Ingredient) + mock_ingredient.get_name.return_value = name + mock_ingredient.get_type.return_value = type_i + mock_ingredient.get_price.return_value = price + + burger.add_ingredient(mock_ingredient) + assert mock_ingredient in burger.ingredients + + def test_remove_ingredient(self, mock_ingredient): + burger = Burger() + burger.add_ingredient(mock_ingredient) + burger.remove_ingredient(0) + assert len(burger.ingredients) == 0 + + def test_move_ingredient(self): + burger = Burger() + ing1 = Mock(spec=Ingredient) + ing2 = Mock(spec=Ingredient) + 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_get_price(self, mock_bun, mock_ingredient): + burger = Burger() + burger.set_buns(mock_bun) + burger.add_ingredient(mock_ingredient) + expected_price = mock_bun.get_price() * 2 + mock_ingredient.get_price() + assert burger.get_price() == expected_price + + def test_get_receipt(self, mock_bun, mock_ingredient): + burger = Burger() + burger.set_buns(mock_bun) + burger.add_ingredient(mock_ingredient) + receipt = burger.get_receipt() + assert "mock bun" in receipt + assert "mock ingredient" in receipt + assert str(mock_bun.get_price() * 2 + mock_ingredient.get_price()) in receipt \ No newline at end of file diff --git a/tests/test_database.py b/tests/test_database.py new file mode 100644 index 000000000..59590b160 --- /dev/null +++ b/tests/test_database.py @@ -0,0 +1,47 @@ +import pytest +from unittest.mock import patch + +from praktikum.database import Database +from praktikum.bun import Bun +from praktikum.ingredient import Ingredient + + +class TestDatabase: + + def test_buns_count(self): + db = Database() + buns = db.available_buns() + assert len(buns) == 3 + + def test_buns_type(self): + db = Database() + buns = db.available_buns() + assert all(isinstance(b, Bun) for b in buns) + + def test_ingredients_count(self): + db = Database() + ingredients = db.available_ingredients() + assert len(ingredients) == 6 + + def test_ingredients_type(self): + db = Database() + ingredients = db.available_ingredients() + assert all(isinstance(i, Ingredient) for i in ingredients) + + @pytest.mark.parametrize("ingredient_name", [ + "hot sauce", "sour cream", "chili sauce", + "cutlet", "dinosaur", "sausage"]) + def test_ingredient_exists(self, ingredient_name): + db = Database() + ingredient = next( + (i for i in db.available_ingredients() if i.get_name() == ingredient_name), + None) + assert ingredient is not None + assert isinstance(ingredient, Ingredient) + + @pytest.mark.parametrize("bun_name", ["black bun", "white bun", "red bun"]) + def test_bun_exists(self, bun_name): + db = Database() + bun = next((b for b in db.available_buns() if b.get_name() == bun_name), None) + assert bun is not None + assert isinstance(bun, Bun) diff --git a/tests/test_ingredient.py b/tests/test_ingredient.py new file mode 100644 index 000000000..48466a2c2 --- /dev/null +++ b/tests/test_ingredient.py @@ -0,0 +1,22 @@ +import pytest +from praktikum.ingredient import Ingredient +from data import IngredientData + + + +class TestForIngredient: + + @pytest.mark.parametrize('ingredient_type, name, price', IngredientData) + def test_get_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', IngredientData) + def test_get_name(self, ingredient_type, name, price): + ingredient = Ingredient(ingredient_type, name, price) + assert ingredient.get_name() == name + + @pytest.mark.parametrize('ingredient_type, name, price', IngredientData) + def test_get_price(self, ingredient_type, name, price): + ingredient = Ingredient(ingredient_type, name, price) + assert ingredient.get_price() == price