From 22928bececbc8cfb7c594de340c518a84cedfc52 Mon Sep 17 00:00:00 2001 From: "m.verma" Date: Mon, 9 Feb 2026 11:52:56 +0300 Subject: [PATCH 1/6] feat: implement unit tests for Task 1 using mocks and parametrization --- .gitignore | 27 +++++++ conftest.py | 19 +++++ praktikum.py => main.py | 0 bun.py => praktikum/bun.py | 0 burger.py => praktikum/burger.py | 0 database.py => praktikum/database.py | 0 ingredient.py => praktikum/ingredient.py | 0 .../ingredient_types.py | 0 pytest.ini | 3 + requirements.txt | Bin 0 -> 102 bytes tests/test_bun.py | 14 ++++ tests/test_burger.py | 70 ++++++++++++++++++ tests/test_database.py | 40 ++++++++++ tests/test_ingredient.py | 15 ++++ 14 files changed, 188 insertions(+) create mode 100644 .gitignore create mode 100644 conftest.py rename praktikum.py => main.py (100%) rename bun.py => praktikum/bun.py (100%) rename burger.py => praktikum/burger.py (100%) rename database.py => praktikum/database.py (100%) rename ingredient.py => praktikum/ingredient.py (100%) rename ingredient_types.py => praktikum/ingredient_types.py (100%) create mode 100644 pytest.ini create mode 100644 requirements.txt create mode 100644 tests/test_bun.py create mode 100644 tests/test_burger.py create mode 100644 tests/test_database.py create mode 100644 tests/test_ingredient.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..26114a413 --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +# Virtual environment +venv/ +.env +.env.* + +# Python cache +__pycache__/ +*.py[cod] +*$py.class + +# Pytest cache +.pytest_cache/ +.coverage +htmlcov/ +pytest_cov/ + +# IDE +.idea/ +.vscode/ +*.iml + +# Logs +*.log + +# System files +.DS_Store +Thumbs.db diff --git a/conftest.py b/conftest.py new file mode 100644 index 000000000..aeeb79452 --- /dev/null +++ b/conftest.py @@ -0,0 +1,19 @@ +import pytest +from unittest.mock import Mock + + +@pytest.fixture +def bun_mock(): + bun = Mock() + bun.get_name.return_value = 'black bun' + bun.get_price.return_value = 100 + return bun + + +@pytest.fixture +def ingredient_mock(): + ingredient = Mock() + ingredient.get_type.return_value = 'SAUCE' + ingredient.get_name.return_value = 'hot sauce' + ingredient.get_price.return_value = 50 + return ingredient diff --git a/praktikum.py b/main.py similarity index 100% rename from praktikum.py rename to main.py 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 100% rename from burger.py rename to praktikum/burger.py 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/pytest.ini b/pytest.ini new file mode 100644 index 000000000..c7b23ecb1 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,3 @@ +[pytest] +pythonpath = . +testpaths = tests diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..14ba20905a413a1150349c1718661fa703bc05c8 GIT binary patch literal 102 zcmezWuYjSFp@boop%_To0-+^?9)kf88!_-Qa4{gu>M|rV Date: Thu, 19 Feb 2026 18:20:51 +0300 Subject: [PATCH 2/6] fix after CR: fixture bun_mock() applied --- tests/test_burger.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/tests/test_burger.py b/tests/test_burger.py index ba9095f93..bed3c15fc 100644 --- a/tests/test_burger.py +++ b/tests/test_burger.py @@ -3,22 +3,18 @@ from praktikum.burger import Burger -def test_set_buns(): +def test_set_buns(bun_mock): burger = Burger() + burger.set_buns(bun_mock) - bun = Mock() - burger.set_buns(bun) + assert burger.bun == bun_mock - assert burger.bun == bun - -def test_add_ingredient(): +def test_add_ingredient(ingredient_mock): burger = Burger() + burger.add_ingredient(ingredient_mock) - ingredient = Mock() - burger.add_ingredient(ingredient) - - assert burger.ingredients == [ingredient] + assert burger.ingredients == [ingredient_mock] def test_remove_ingredient(): From 0d6b5123c1dda54a196491183570e34e6ec6ad57 Mon Sep 17 00:00:00 2001 From: "m.verma" Date: Thu, 19 Feb 2026 20:49:20 +0300 Subject: [PATCH 3/6] fix after CRL: add Burger.get_receipt tests for empty and populated ingredients --- tests/test_burger.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/tests/test_burger.py b/tests/test_burger.py index bed3c15fc..e4eac3dfb 100644 --- a/tests/test_burger.py +++ b/tests/test_burger.py @@ -64,3 +64,40 @@ def test_get_price(bun_price, ing_prices, expected): burger.add_ingredient(ingredient) assert burger.get_price() == expected + + +def test_get_receipt_without_ingredients(bun_mock): + burger = Burger() + burger.set_buns(bun_mock) + + expected = '(==== black bun ====)\n(==== black bun ====)\n\nPrice: 200' + + assert burger.get_receipt() == expected + + +def test_get_receipt_with_ingredients(bun_mock): + burger = Burger() + burger.set_buns(bun_mock) + + sauce = Mock() + sauce.get_type.return_value = 'SAUCE' + sauce.get_name.return_value = 'hot sauce' + sauce.get_price.return_value = 50 + + filling = Mock() + filling.get_type.return_value = 'FILLING' + filling.get_name.return_value = 'cutlet' + filling.get_price.return_value = 100 + + burger.add_ingredient(sauce) + burger.add_ingredient(filling) + + expected = ( + '(==== black bun ====)\n' + '= sauce hot sauce =\n' + '= filling cutlet =\n' + '(==== black bun ====)\n\n' + 'Price: 350' + ) + + assert burger.get_receipt() == expected From fba6a1bc7248f077ec9629f009c52134ea8b5747 Mon Sep 17 00:00:00 2001 From: "m.verma" Date: Thu, 19 Feb 2026 20:53:17 +0300 Subject: [PATCH 4/6] fix after CR: ref: one method - one test --- tests/test_bun.py | 12 +++++++++++- tests/test_ingredient.py | 20 +++++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/tests/test_bun.py b/tests/test_bun.py index ad646f0e9..49827fc44 100644 --- a/tests/test_bun.py +++ b/tests/test_bun.py @@ -7,8 +7,18 @@ ('white bun', 200), ('red bun', 300), ]) -def test_bun_getters(name, price): +def test_bun_get_name(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), +]) +def test_bun_get_price(name, price): + bun = Bun(name, price) + assert bun.get_price() == price diff --git a/tests/test_ingredient.py b/tests/test_ingredient.py index 46690d7a7..628ef8f3a 100644 --- a/tests/test_ingredient.py +++ b/tests/test_ingredient.py @@ -7,9 +7,27 @@ (INGREDIENT_TYPE_SAUCE, 'hot sauce', 100), (INGREDIENT_TYPE_FILLING, 'cutlet', 200), ]) -def test_ingredient_getters(ingredient_type, name, price): +def test_ingredient_get_type(ingredient_type, name, price): ing = Ingredient(ingredient_type, name, price) assert ing.get_type() == ingredient_type + + +@pytest.mark.parametrize('ingredient_type, name, price', [ + (INGREDIENT_TYPE_SAUCE, 'hot sauce', 100), + (INGREDIENT_TYPE_FILLING, 'cutlet', 200), +]) +def test_ingredient_get_name(ingredient_type, name, price): + ing = Ingredient(ingredient_type, name, price) + assert ing.get_name() == name + + +@pytest.mark.parametrize('ingredient_type, name, price', [ + (INGREDIENT_TYPE_SAUCE, 'hot sauce', 100), + (INGREDIENT_TYPE_FILLING, 'cutlet', 200), +]) +def test_ingredient_get_price(ingredient_type, name, price): + ing = Ingredient(ingredient_type, name, price) + assert ing.get_price() == price From a2033e4a93127fb80b5b4eb6721a00cdbc337f31 Mon Sep 17 00:00:00 2001 From: "m.verma" Date: Thu, 19 Feb 2026 20:58:09 +0300 Subject: [PATCH 5/6] fix after CR: ref: tests made class-based pytest layout across all modules --- tests/test_bun.py | 34 +++++----- tests/test_burger.py | 137 +++++++++++++++++++-------------------- tests/test_database.py | 51 +++++++-------- tests/test_ingredient.py | 55 ++++++++-------- 4 files changed, 135 insertions(+), 142 deletions(-) diff --git a/tests/test_bun.py b/tests/test_bun.py index 49827fc44..c1c8fab7e 100644 --- a/tests/test_bun.py +++ b/tests/test_bun.py @@ -2,23 +2,23 @@ from praktikum.bun import Bun -@pytest.mark.parametrize('name,price', [ - ('black bun', 100), - ('white bun', 200), - ('red bun', 300), -]) -def test_bun_get_name(name, price): - bun = Bun(name, price) +class TestBun: + @pytest.mark.parametrize('name,price', [ + ('black bun', 100), + ('white bun', 200), + ('red bun', 300), + ]) + def test_bun_get_name(self, name, price): + bun = Bun(name, price) - assert bun.get_name() == name + assert bun.get_name() == name + @pytest.mark.parametrize('name,price', [ + ('black bun', 100), + ('white bun', 200), + ('red bun', 300), + ]) + def test_bun_get_price(self, name, price): + bun = Bun(name, price) -@pytest.mark.parametrize('name,price', [ - ('black bun', 100), - ('white bun', 200), - ('red bun', 300), -]) -def test_bun_get_price(name, price): - bun = Bun(name, price) - - assert bun.get_price() == price + assert bun.get_price() == price diff --git a/tests/test_burger.py b/tests/test_burger.py index e4eac3dfb..0a58500de 100644 --- a/tests/test_burger.py +++ b/tests/test_burger.py @@ -3,101 +3,96 @@ from praktikum.burger import Burger -def test_set_buns(bun_mock): - burger = Burger() - burger.set_buns(bun_mock) +class TestBurger: + def test_set_buns(self, bun_mock): + burger = Burger() + burger.set_buns(bun_mock) - assert burger.bun == bun_mock + assert burger.bun == bun_mock + def test_add_ingredient(self, ingredient_mock): + burger = Burger() + burger.add_ingredient(ingredient_mock) -def test_add_ingredient(ingredient_mock): - burger = Burger() - burger.add_ingredient(ingredient_mock) + assert burger.ingredients == [ingredient_mock] - assert burger.ingredients == [ingredient_mock] + def test_remove_ingredient(self): + burger = Burger() + i1 = Mock() + i2 = Mock() -def test_remove_ingredient(): - burger = Burger() + burger.add_ingredient(i1) + burger.add_ingredient(i2) - i1 = Mock() - i2 = Mock() + burger.remove_ingredient(0) - burger.add_ingredient(i1) - burger.add_ingredient(i2) + assert burger.ingredients == [i2] - burger.remove_ingredient(0) + def test_move_ingredient(self): + burger = Burger() - assert burger.ingredients == [i2] + i1 = Mock() + i2 = Mock() + i3 = Mock() + burger.ingredients = [i1, i2, i3] -def test_move_ingredient(): - burger = Burger() + burger.move_ingredient(0, 2) - i1 = Mock() - i2 = Mock() - i3 = Mock() + assert burger.ingredients == [i2, i3, i1] - burger.ingredients = [i1, i2, i3] + @pytest.mark.parametrize('bun_price, ing_prices, expected', [ + (100, [], 200), + (100, [50], 250), + (200, [10, 20], 430), + ]) + def test_get_price(self, bun_price, ing_prices, expected): + burger = Burger() - burger.move_ingredient(0, 2) + bun = Mock() + bun.get_price.return_value = bun_price + burger.set_buns(bun) - assert burger.ingredients == [i2, i3, i1] + for price in ing_prices: + ingredient = Mock() + ingredient.get_price.return_value = price + burger.add_ingredient(ingredient) -@pytest.mark.parametrize('bun_price, ing_prices, expected', [ - (100, [], 200), - (100, [50], 250), - (200, [10, 20], 430), -]) -def test_get_price(bun_price, ing_prices, expected): - burger = Burger() + assert burger.get_price() == expected - bun = Mock() - bun.get_price.return_value = bun_price - burger.set_buns(bun) + def test_get_receipt_without_ingredients(self, bun_mock): + burger = Burger() + burger.set_buns(bun_mock) - for price in ing_prices: - ingredient = Mock() - ingredient.get_price.return_value = price + expected = '(==== black bun ====)\n(==== black bun ====)\n\nPrice: 200' - burger.add_ingredient(ingredient) + assert burger.get_receipt() == expected - assert burger.get_price() == expected + def test_get_receipt_with_ingredients(self, bun_mock): + burger = Burger() + burger.set_buns(bun_mock) + sauce = Mock() + sauce.get_type.return_value = 'SAUCE' + sauce.get_name.return_value = 'hot sauce' + sauce.get_price.return_value = 50 -def test_get_receipt_without_ingredients(bun_mock): - burger = Burger() - burger.set_buns(bun_mock) + filling = Mock() + filling.get_type.return_value = 'FILLING' + filling.get_name.return_value = 'cutlet' + filling.get_price.return_value = 100 - expected = '(==== black bun ====)\n(==== black bun ====)\n\nPrice: 200' + burger.add_ingredient(sauce) + burger.add_ingredient(filling) - assert burger.get_receipt() == expected + expected = ( + '(==== black bun ====)\n' + '= sauce hot sauce =\n' + '= filling cutlet =\n' + '(==== black bun ====)\n\n' + 'Price: 350' + ) - -def test_get_receipt_with_ingredients(bun_mock): - burger = Burger() - burger.set_buns(bun_mock) - - sauce = Mock() - sauce.get_type.return_value = 'SAUCE' - sauce.get_name.return_value = 'hot sauce' - sauce.get_price.return_value = 50 - - filling = Mock() - filling.get_type.return_value = 'FILLING' - filling.get_name.return_value = 'cutlet' - filling.get_price.return_value = 100 - - burger.add_ingredient(sauce) - burger.add_ingredient(filling) - - expected = ( - '(==== black bun ====)\n' - '= sauce hot sauce =\n' - '= filling cutlet =\n' - '(==== black bun ====)\n\n' - 'Price: 350' - ) - - assert burger.get_receipt() == expected + assert burger.get_receipt() == expected diff --git a/tests/test_database.py b/tests/test_database.py index 91b841659..d19508ddd 100644 --- a/tests/test_database.py +++ b/tests/test_database.py @@ -2,39 +2,38 @@ from praktikum.ingredient_types import INGREDIENT_TYPE_SAUCE, INGREDIENT_TYPE_FILLING -def test_available_buns(): - db = Database() - buns = db.available_buns() +class TestDatabase: + def test_available_buns(self): + db = Database() + buns = db.available_buns() - assert len(buns) == 3 + assert len(buns) == 3 - names = [] - for bun in buns: - names.append(bun.get_name()) + names = [] + for bun in buns: + names.append(bun.get_name()) - assert names == ['black bun', 'white bun', 'red bun'] + assert names == ['black bun', 'white bun', 'red bun'] + def test_available_ingredients(self): + db = Database() + ingredients = db.available_ingredients() -def test_available_ingredients(): - db = Database() - ingredients = db.available_ingredients() + assert len(ingredients) == 6 - assert len(ingredients) == 6 + def test_ingredient_types_count(self): + db = Database() + ingredients = db.available_ingredients() + sauce_count = 0 + filling_count = 0 -def test_ingredient_types_count(): - db = Database() - ingredients = db.available_ingredients() + for ing in ingredients: + if ing.get_type() == INGREDIENT_TYPE_SAUCE: + sauce_count += 1 - sauce_count = 0 - filling_count = 0 + if ing.get_type() == INGREDIENT_TYPE_FILLING: + filling_count += 1 - for ing in ingredients: - if ing.get_type() == INGREDIENT_TYPE_SAUCE: - sauce_count += 1 - - if ing.get_type() == INGREDIENT_TYPE_FILLING: - filling_count += 1 - - assert sauce_count == 3 - assert filling_count == 3 + assert sauce_count == 3 + assert filling_count == 3 diff --git a/tests/test_ingredient.py b/tests/test_ingredient.py index 628ef8f3a..a6ba2c895 100644 --- a/tests/test_ingredient.py +++ b/tests/test_ingredient.py @@ -3,31 +3,30 @@ from praktikum.ingredient_types import INGREDIENT_TYPE_SAUCE, INGREDIENT_TYPE_FILLING -@pytest.mark.parametrize('ingredient_type, name, price', [ - (INGREDIENT_TYPE_SAUCE, 'hot sauce', 100), - (INGREDIENT_TYPE_FILLING, 'cutlet', 200), -]) -def test_ingredient_get_type(ingredient_type, name, price): - ing = Ingredient(ingredient_type, name, price) - - assert ing.get_type() == ingredient_type - - -@pytest.mark.parametrize('ingredient_type, name, price', [ - (INGREDIENT_TYPE_SAUCE, 'hot sauce', 100), - (INGREDIENT_TYPE_FILLING, 'cutlet', 200), -]) -def test_ingredient_get_name(ingredient_type, name, price): - ing = Ingredient(ingredient_type, name, price) - - assert ing.get_name() == name - - -@pytest.mark.parametrize('ingredient_type, name, price', [ - (INGREDIENT_TYPE_SAUCE, 'hot sauce', 100), - (INGREDIENT_TYPE_FILLING, 'cutlet', 200), -]) -def test_ingredient_get_price(ingredient_type, name, price): - ing = Ingredient(ingredient_type, name, price) - - assert ing.get_price() == price +class TestIngredient: + @pytest.mark.parametrize('ingredient_type, name, price', [ + (INGREDIENT_TYPE_SAUCE, 'hot sauce', 100), + (INGREDIENT_TYPE_FILLING, 'cutlet', 200), + ]) + def test_ingredient_get_type(self, ingredient_type, name, price): + ing = Ingredient(ingredient_type, name, price) + + assert ing.get_type() == ingredient_type + + @pytest.mark.parametrize('ingredient_type, name, price', [ + (INGREDIENT_TYPE_SAUCE, 'hot sauce', 100), + (INGREDIENT_TYPE_FILLING, 'cutlet', 200), + ]) + def test_ingredient_get_name(self, ingredient_type, name, price): + ing = Ingredient(ingredient_type, name, price) + + assert ing.get_name() == name + + @pytest.mark.parametrize('ingredient_type, name, price', [ + (INGREDIENT_TYPE_SAUCE, 'hot sauce', 100), + (INGREDIENT_TYPE_FILLING, 'cutlet', 200), + ]) + def test_ingredient_get_price(self, ingredient_type, name, price): + ing = Ingredient(ingredient_type, name, price) + + assert ing.get_price() == price From 7c337715f552f426f8358af71ecc4cd62fbf31ca Mon Sep 17 00:00:00 2001 From: "m.verma" Date: Thu, 19 Feb 2026 21:03:21 +0300 Subject: [PATCH 6/6] updated coverage report --- coverage.xml | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 coverage.xml diff --git a/coverage.xml b/coverage.xml new file mode 100644 index 000000000..ab4a36937 --- /dev/null +++ b/coverage.xml @@ -0,0 +1,108 @@ + + + + + + C:\Users\masha\Documents\Education Practice\dev\Project\Task_1\praktikum + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +