diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..98c8621b8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +__pycache__/ +.pytest_cache/ +.coverage +.DS_Store diff --git a/README.md b/README.md index 272081708..86d0fbc7e 100644 --- a/README.md +++ b/README.md @@ -8,17 +8,3 @@ Процент покрытия 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/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/data.py b/data.py new file mode 100644 index 000000000..aa399b907 --- /dev/null +++ b/data.py @@ -0,0 +1,27 @@ +from ingredient_types import INGREDIENT_TYPE_SAUCE, INGREDIENT_TYPE_FILLING + +BUN_NAME = "black bun" +BUN_PRICE = 100 + +SAUCE_TYPE = INGREDIENT_TYPE_SAUCE +SAUCE_NAME = "hot sauce" +SAUCE_PRICE = 100 + +FILLING_TYPE = INGREDIENT_TYPE_FILLING +FILLING_NAME = "cutlet" +FILLING_PRICE = 100 + +SECOND_SAUCE_NAME = "sour cream" +SECOND_SAUCE_PRICE = 200 + +MOVED_INGREDIENT_NAMES_FROM_FIRST_TO_LAST = [ + FILLING_NAME, + SECOND_SAUCE_NAME, + SAUCE_NAME, +] + +MOVED_INGREDIENT_NAMES_FROM_LAST_TO_FIRST = [ + SECOND_SAUCE_NAME, + SAUCE_NAME, + FILLING_NAME, +] \ No newline at end of file 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/pytest.ini b/pytest.ini new file mode 100644 index 000000000..0fbcf85f5 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,4 @@ +[pytest] +testpaths = tests +python_files = test_*.py +pythonpath = . \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..549199a4b --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +pytest==8.3.3 +pytest-cov==5.0.0 \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 000000000..708f81419 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,44 @@ +import pytest +from unittest.mock import Mock + +from burger import Burger +from bun import Bun +from ingredient import Ingredient +from data import ( + BUN_NAME, + BUN_PRICE, + SAUCE_TYPE, + SAUCE_NAME, + SAUCE_PRICE, +) + +@pytest.fixture +def burger(): + return Burger() + + +@pytest.fixture +def bun(): + return Bun(BUN_NAME, BUN_PRICE) + + +@pytest.fixture +def ingredient(): + return Ingredient(SAUCE_TYPE, SAUCE_NAME, SAUCE_PRICE) + + +@pytest.fixture +def mock_bun(): + bun = Mock() + bun.get_name.return_value = BUN_NAME + bun.get_price.return_value = BUN_PRICE + return bun + + +@pytest.fixture +def mock_ingredient(): + ingredient = Mock() + ingredient.get_type.return_value = SAUCE_TYPE + ingredient.get_name.return_value = SAUCE_NAME + ingredient.get_price.return_value = SAUCE_PRICE + return ingredient \ No newline at end of file diff --git a/tests/test_bun.py b/tests/test_bun.py new file mode 100644 index 000000000..c8fdd953c --- /dev/null +++ b/tests/test_bun.py @@ -0,0 +1,8 @@ +from data import BUN_NAME, BUN_PRICE + +def test_bun_get_name(bun): + assert bun.get_name() == BUN_NAME + + +def test_bun_get_price(bun): + assert bun.get_price() == BUN_PRICE \ No newline at end of file diff --git a/tests/test_burger.py b/tests/test_burger.py new file mode 100644 index 000000000..64bcab8f1 --- /dev/null +++ b/tests/test_burger.py @@ -0,0 +1,98 @@ +import pytest +from unittest.mock import Mock +from data import ( + BUN_NAME, + BUN_PRICE, + SAUCE_TYPE, + SAUCE_NAME, + SAUCE_PRICE, + FILLING_TYPE, + FILLING_NAME, + FILLING_PRICE, + SECOND_SAUCE_NAME, + SECOND_SAUCE_PRICE, + MOVED_INGREDIENT_NAMES_FROM_FIRST_TO_LAST, + MOVED_INGREDIENT_NAMES_FROM_LAST_TO_FIRST, +) + +def make_ingredient(ingredient_type, name, price): + ingredient = Mock() + ingredient.get_type.return_value = ingredient_type + ingredient.get_name.return_value = name + ingredient.get_price.return_value = price + return ingredient + + +def test_set_buns_sets_bun(burger, mock_bun): + burger.set_buns(mock_bun) + + assert burger.bun == mock_bun + + +def test_add_ingredient_adds_ingredient(burger, mock_ingredient): + burger.add_ingredient(mock_ingredient) + + assert burger.ingredients == [mock_ingredient] + + +def test_remove_ingredient_removes_ingredient(burger): + ingredient1 = make_ingredient(SAUCE_TYPE, SAUCE_NAME, SAUCE_PRICE) + ingredient2 = make_ingredient(FILLING_TYPE, FILLING_NAME, FILLING_PRICE) + burger.ingredients = [ingredient1, ingredient2] + + burger.remove_ingredient(0) + + assert burger.ingredients == [ingredient2] + + +@pytest.mark.parametrize( + "index,new_index,expected", + [ + (0, 2, [FILLING_NAME, SECOND_SAUCE_NAME, SAUCE_NAME]), + (2, 0, [SECOND_SAUCE_NAME, SAUCE_NAME, FILLING_NAME]), + ], +) +def test_move_ingredient_changes_order(burger, index, new_index, expected): + burger.ingredients = [ + make_ingredient(SAUCE_TYPE, SAUCE_NAME, SAUCE_PRICE), + make_ingredient(FILLING_TYPE, FILLING_NAME, FILLING_PRICE), + make_ingredient(SAUCE_TYPE, SECOND_SAUCE_NAME, SECOND_SAUCE_PRICE), + ] + + burger.move_ingredient(index, new_index) + + result = [ingredient.get_name() for ingredient in burger.ingredients] + assert result == expected + + +@pytest.mark.parametrize( + "bun_price,ingredient_prices,expected_price", + [ + (BUN_PRICE, [SAUCE_PRICE, FILLING_PRICE], 400), + (FILLING_PRICE, [], 200), + ], +) +def test_get_price_returns_bun_price_twice_plus_ingredients( + burger, mock_bun, bun_price, ingredient_prices, expected_price +): + mock_bun.get_price.return_value = bun_price + burger.set_buns(mock_bun) + for price in ingredient_prices: + burger.add_ingredient(make_ingredient(SAUCE_TYPE, SAUCE_NAME, price)) + + assert burger.get_price() == expected_price + + +def test_get_receipt_returns_burger_description_and_price(burger, mock_bun): + burger.set_buns(mock_bun) + burger.add_ingredient(make_ingredient(SAUCE_TYPE, SAUCE_NAME, SAUCE_PRICE)) + burger.add_ingredient(make_ingredient(FILLING_TYPE, FILLING_NAME, FILLING_PRICE)) + expected_receipt = ( + f"(==== {BUN_NAME} ====)\n" + f"= sauce {SAUCE_NAME} =\n" + f"= filling {FILLING_NAME} =\n" + f"(==== {BUN_NAME} ====)\n\n" + "Price: 400" + ) + + assert burger.get_receipt() == expected_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..5b7460b9a --- /dev/null +++ b/tests/test_database.py @@ -0,0 +1,15 @@ +from database import Database + + +def test_available_buns_returns_buns(): + db = Database() + buns = db.available_buns() + + assert len(buns) == 3 + + +def test_available_ingredients_returns_ingredients(): + db = Database() + ingredients = db.available_ingredients() + + assert len(ingredients) == 6 \ No newline at end of file diff --git a/tests/test_ingredient.py b/tests/test_ingredient.py new file mode 100644 index 000000000..ef1e8bfa9 --- /dev/null +++ b/tests/test_ingredient.py @@ -0,0 +1,12 @@ +from data import SAUCE_TYPE, SAUCE_NAME, SAUCE_PRICE + +def test_ingredient_get_name(ingredient): + assert ingredient.get_name() == SAUCE_NAME + + +def test_ingredient_get_price(ingredient): + assert ingredient.get_price() == SAUCE_PRICE + + +def test_ingredient_get_type(ingredient): + assert ingredient.get_type() == SAUCE_TYPE \ No newline at end of file