From 2732a8c3593ea6ef73f2099223c4cb807020fc5c Mon Sep 17 00:00:00 2001 From: Alina Khazeeva Date: Mon, 13 Jul 2026 22:45:42 +0300 Subject: [PATCH 1/2] add tests and complete code coverage --- .gitignore | 25 +++++++ README.md | 69 +++++++++++++++---- __init__.py => praktikum/__init__.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 praktikum.py => praktikum/praktikum.py | 2 - requirements.txt | 3 + tests/conftest.py | 24 +++++++ tests/test_bun.py | 16 +++++ tests/test_burger.py | 54 +++++++++++++++ tests/test_database.py | 13 ++++ tests/test_ingredient.py | 19 +++++ 15 files changed, 210 insertions(+), 15 deletions(-) create mode 100644 .gitignore rename __init__.py => praktikum/__init__.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%) rename praktikum.py => praktikum/praktikum.py (99%) create mode 100644 requirements.txt create mode 100644 tests/conftest.py 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..1a0ca9295 --- /dev/null +++ b/.gitignore @@ -0,0 +1,25 @@ +__pycache__/ +*.py[cod] +*.pyo +*.pyd +*.pytest_cache/ +.pytest_cache/ +*.egg-info/ +dist/ +build/ +venv/ +env/ +.venv/ +.idea/ +.vscode/ +*.swp +*.swo +.DS_Store +*.log +selenium-screenshots/ +screenshots/ +videos/ +.cache/ +htmlcov/ +.coverage +coverage.xml \ No newline at end of file diff --git a/README.md b/README.md index 272081708..ad8965eb4 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,67 @@ -## Задание 1: Юнит-тесты +# Задание 1. Юнит-тесты +## Автотесты для проверки программы, которая помогает заказать бургер в Stellar Burgers +### Реализованные сценарии -### Автотесты для проверки программы, которая помогает заказать бургер в Stellar Burgers +Разработаны юнит-тесты для следующих классов: +- `Bun` +- `Burger` +- `Ingredient` +- `Database` -### Реализованные сценарии +Использованы: +- `pytest` +- параметризация (`pytest.mark.parametrize`) +- моки (`unittest.mock`) + +Процент покрытия кода — **78%**. + +HTML-отчет о покрытии можно сгенерировать командой: + +```bash +python3 -m pytest --cov=praktikum --cov-report=html +``` + +## Структура проекта + +```text +praktikum/ + bun.py + burger.py + database.py + ingredient.py + ingredient_types.py + praktikum.py + +tests/ + conftest.py + test_bun.py + test_burger.py + test_database.py + test_ingredient.py +``` -Созданы юнит-тесты, покрывающие классы `Bun`, `Burger`, `Ingredient`, `Database` +## Установка зависимостей -Процент покрытия 100% (отчет: `htmlcov/index.html`) +```bash +pip install -r requirements.txt +``` -### Структура проекта +## Запуск тестов -- `praktikum` - пакет, содержащий код программы -- `tests` - пакет, содержащий тесты, разделенные по классам. Например, `bun_test.py`, `burger_test.py` и т.д. +```bash +python3 -m pytest +``` -### Запуск автотестов +## Запуск тестов с отчетом о покрытии -**Установка зависимостей** +Отчет в консоли: -> `$ pip install -r requirements.txt` +```bash +python3 -m pytest --cov=praktikum --cov-report=term-missing +``` -**Запуск автотестов и создание HTML-отчета о покрытии** +HTML-отчет: -> `$ pytest --cov=praktikum --cov-report=html` +```bash +python3 -m pytest --cov=praktikum --cov-report=html +``` \ No newline at end of file diff --git a/__init__.py b/praktikum/__init__.py similarity index 100% rename from __init__.py rename to praktikum/__init__.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/praktikum.py b/praktikum/praktikum.py similarity index 99% rename from praktikum.py rename to praktikum/praktikum.py index ec522fa6d..73012525d 100644 --- a/praktikum.py +++ b/praktikum/praktikum.py @@ -1,11 +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 - def main(): # Инициализируем базу данных database: Database = Database() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..d9d960e3d --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +pytest==9.0.2 +pytest-cov==7.1.0 +allure-pytest==2.16.0 \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 000000000..dd7ed1307 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,24 @@ +import pytest +from praktikum.bun import Bun +from praktikum.ingredient import Ingredient +from praktikum.burger import Burger +from praktikum.ingredient_types import ( + INGREDIENT_TYPE_SAUCE, + INGREDIENT_TYPE_FILLING +) + +@pytest.fixture +def bun(): + return Bun("white bun", 200) + +@pytest.fixture +def sauce(): + return Ingredient(INGREDIENT_TYPE_SAUCE, "hot sauce", 100) + +@pytest.fixture +def filling(): + return Ingredient(INGREDIENT_TYPE_FILLING, "cutlet", 300) + +@pytest.fixture +def burger(): + return Burger() diff --git a/tests/test_bun.py b/tests/test_bun.py new file mode 100644 index 000000000..77f85e203 --- /dev/null +++ b/tests/test_bun.py @@ -0,0 +1,16 @@ +import pytest +from praktikum.bun import Bun + +@pytest.mark.parametrize( + "name, price", + [ + ("white bun", 200), + ("black bun", 100), + ("red bun", 300) + ] +) +def test_bun_fields(name, price): + bun = Bun(name, price) + assert bun.get_name() == name + assert bun.get_price() == 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..3de9cfbb1 --- /dev/null +++ b/tests/test_burger.py @@ -0,0 +1,54 @@ +from unittest.mock import Mock + +def test_set_bun(burger): + bun = Mock() + burger.set_buns(bun) + assert burger.bun == bun + +def test_add_ingredient(burger, sauce): + burger.add_ingredient(sauce) + assert sauce in burger.ingredients + +def test_remove_ingredient(burger, sauce, filling): + burger.add_ingredient(sauce) + burger.add_ingredient(filling) + burger.remove_ingredient(0) + assert burger.ingredients == [filling] + +def test_move_ingredient(burger, sauce, filling): + burger.add_ingredient(sauce) + burger.add_ingredient(filling) + burger.move_ingredient(0, 1) + assert burger.ingredients == [filling, sauce] + +def test_get_price(burger): + bun = Mock() + bun.get_price.return_value = 200 + ingredient1 = Mock() + ingredient1.get_price.return_value = 100 + + ingredient2 = Mock() + ingredient2.get_price.return_value = 300 + burger.set_buns(bun) + burger.add_ingredient(ingredient1) + burger.add_ingredient(ingredient2) + assert burger.get_price() == 800 + +def test_get_receipt(burger): + bun = Mock() + bun.get_name.return_value = "white bun" + bun.get_price.return_value = 200 + + ingredient = Mock() + ingredient.get_type.return_value = "SAUCE" + ingredient.get_name.return_value = "hot sauce" + ingredient.get_price.return_value = 100 + burger.set_buns(bun) + burger.add_ingredient(ingredient) + expected = ( + "(==== white bun ====)\n" + "= sauce hot sauce =\n" + "(==== white bun ====)\n\n" + "Price: 500" + ) + assert burger.get_receipt() == expected diff --git a/tests/test_database.py b/tests/test_database.py new file mode 100644 index 000000000..d94c960c3 --- /dev/null +++ b/tests/test_database.py @@ -0,0 +1,13 @@ +from praktikum.database import Database + +def test_database_contains_buns(): + database = Database() + buns = database.available_buns() + assert len(buns) == 3 + assert buns[0].get_name() == "black bun" + +def test_database_contains_ingredients(): + database = Database() + ingredients = database.available_ingredients() + assert len(ingredients) == 6 + assert ingredients[0].get_name() == "hot sauce" diff --git a/tests/test_ingredient.py b/tests/test_ingredient.py new file mode 100644 index 000000000..7243e211a --- /dev/null +++ b/tests/test_ingredient.py @@ -0,0 +1,19 @@ +import pytest +from praktikum.ingredient import Ingredient +from praktikum.ingredient_types import ( + INGREDIENT_TYPE_FILLING, + INGREDIENT_TYPE_SAUCE +) + +@pytest.mark.parametrize( + "ingredient_type, name, price", + [ + (INGREDIENT_TYPE_SAUCE, "hot sauce", 100), + (INGREDIENT_TYPE_FILLING, "cutlet", 300), + ] +) +def test_ingredient_fields(ingredient_type, name, price): + ingredient = Ingredient(ingredient_type, name, price) + assert ingredient.get_type() == ingredient_type + assert ingredient.get_name() == name + assert ingredient.get_price() == price From fdb4e8ab595d4a4ba1841c515730d23de30150fc Mon Sep 17 00:00:00 2001 From: Alina Khazeeva Date: Sun, 26 Jul 2026 14:26:28 +0300 Subject: [PATCH 2/2] update tests and coverage --- tests/test_bun.py | 32 ++++++++---- tests/test_burger.py | 105 ++++++++++++++++++++------------------- tests/test_database.py | 21 ++++---- tests/test_ingredient.py | 46 ++++++++++++----- 4 files changed, 120 insertions(+), 84 deletions(-) diff --git a/tests/test_bun.py b/tests/test_bun.py index 77f85e203..872bedb4a 100644 --- a/tests/test_bun.py +++ b/tests/test_bun.py @@ -1,16 +1,28 @@ import pytest from praktikum.bun import Bun -@pytest.mark.parametrize( - "name, price", +class TestBun: + @pytest.mark.parametrize( + "name", [ - ("white bun", 200), - ("black bun", 100), - ("red bun", 300) + "white bun", + "black bun", + "red bun" ] ) -def test_bun_fields(name, price): - bun = Bun(name, price) - assert bun.get_name() == name - assert bun.get_price() == price - \ No newline at end of file + def test_get_name(self, name): + bun = Bun(name, 200) + assert bun.get_name() == name + + @pytest.mark.parametrize( + "price", + [ + 100, + 200, + 300 + ] + ) + def test_get_price(self, price): + bun = Bun("white bun", price) + assert bun.get_price() == price + \ No newline at end of file diff --git a/tests/test_burger.py b/tests/test_burger.py index 3de9cfbb1..1bb916945 100644 --- a/tests/test_burger.py +++ b/tests/test_burger.py @@ -1,54 +1,55 @@ from unittest.mock import Mock -def test_set_bun(burger): - bun = Mock() - burger.set_buns(bun) - assert burger.bun == bun - -def test_add_ingredient(burger, sauce): - burger.add_ingredient(sauce) - assert sauce in burger.ingredients - -def test_remove_ingredient(burger, sauce, filling): - burger.add_ingredient(sauce) - burger.add_ingredient(filling) - burger.remove_ingredient(0) - assert burger.ingredients == [filling] - -def test_move_ingredient(burger, sauce, filling): - burger.add_ingredient(sauce) - burger.add_ingredient(filling) - burger.move_ingredient(0, 1) - assert burger.ingredients == [filling, sauce] - -def test_get_price(burger): - bun = Mock() - bun.get_price.return_value = 200 - ingredient1 = Mock() - ingredient1.get_price.return_value = 100 - - ingredient2 = Mock() - ingredient2.get_price.return_value = 300 - burger.set_buns(bun) - burger.add_ingredient(ingredient1) - burger.add_ingredient(ingredient2) - assert burger.get_price() == 800 - -def test_get_receipt(burger): - bun = Mock() - bun.get_name.return_value = "white bun" - bun.get_price.return_value = 200 - - ingredient = Mock() - ingredient.get_type.return_value = "SAUCE" - ingredient.get_name.return_value = "hot sauce" - ingredient.get_price.return_value = 100 - burger.set_buns(bun) - burger.add_ingredient(ingredient) - expected = ( - "(==== white bun ====)\n" - "= sauce hot sauce =\n" - "(==== white bun ====)\n\n" - "Price: 500" - ) - assert burger.get_receipt() == expected +class TestBurger: + def test_set_bun(self, burger): + bun = Mock() + burger.set_buns(bun) + assert burger.bun == bun + + def test_add_ingredient(self,burger, sauce): + burger.add_ingredient(sauce) + assert sauce in burger.ingredients + + def test_remove_ingredient(self, burger, sauce, filling): + burger.add_ingredient(sauce) + burger.add_ingredient(filling) + burger.remove_ingredient(0) + assert burger.ingredients == [filling] + + def test_move_ingredient(self, burger, sauce, filling): + burger.add_ingredient(sauce) + burger.add_ingredient(filling) + burger.move_ingredient(0, 1) + assert burger.ingredients == [filling, sauce] + + def test_get_price(self, burger): + bun = Mock() + bun.get_price.return_value = 200 + ingredient_1 = Mock() + ingredient_1.get_price.return_value = 100 + + ingredient_2 = Mock() + ingredient_2.get_price.return_value = 300 + burger.set_buns(bun) + burger.add_ingredient(ingredient_1) + burger.add_ingredient(ingredient_2) + assert burger.get_price() == 800 + + def test_get_receipt(self, burger): + bun = Mock() + bun.get_name.return_value = "white bun" + bun.get_price.return_value = 200 + + ingredient = Mock() + ingredient.get_type.return_value = "SAUCE" + ingredient.get_name.return_value = "hot sauce" + ingredient.get_price.return_value = 100 + burger.set_buns(bun) + burger.add_ingredient(ingredient) + expected = ( + "(==== white bun ====)\n" + "= sauce hot sauce =\n" + "(==== white bun ====)\n\n" + "Price: 500" + ) + assert burger.get_receipt() == expected diff --git a/tests/test_database.py b/tests/test_database.py index d94c960c3..6779a7edc 100644 --- a/tests/test_database.py +++ b/tests/test_database.py @@ -1,13 +1,14 @@ from praktikum.database import Database -def test_database_contains_buns(): - database = Database() - buns = database.available_buns() - assert len(buns) == 3 - assert buns[0].get_name() == "black bun" +class TestDatabase: + def test_database_contains_buns(self): + database = Database() + buns = database.available_buns() + assert len(buns) == 3 + assert buns[0].get_name() == "black bun" -def test_database_contains_ingredients(): - database = Database() - ingredients = database.available_ingredients() - assert len(ingredients) == 6 - assert ingredients[0].get_name() == "hot sauce" + def test_database_contains_ingredients(self): + database = Database() + ingredients = database.available_ingredients() + assert len(ingredients) == 6 + assert ingredients[0].get_name() == "hot sauce" diff --git a/tests/test_ingredient.py b/tests/test_ingredient.py index 7243e211a..8081d3ad0 100644 --- a/tests/test_ingredient.py +++ b/tests/test_ingredient.py @@ -5,15 +5,37 @@ INGREDIENT_TYPE_SAUCE ) -@pytest.mark.parametrize( - "ingredient_type, name, price", - [ - (INGREDIENT_TYPE_SAUCE, "hot sauce", 100), - (INGREDIENT_TYPE_FILLING, "cutlet", 300), - ] -) -def test_ingredient_fields(ingredient_type, name, price): - ingredient = Ingredient(ingredient_type, name, price) - assert ingredient.get_type() == ingredient_type - assert ingredient.get_name() == name - assert ingredient.get_price() == price +class TestIngredient: + @pytest.mark.parametrize( + "ingredient_type", + [ + INGREDIENT_TYPE_SAUCE, + INGREDIENT_TYPE_FILLING, + ] + ) + def test_get_type(self, ingredient_type): + ingredient = Ingredient(ingredient_type, "test", 100) + assert ingredient.get_type() == ingredient_type + + @pytest.mark.parametrize( + "name", + [ + "hot sauce", + "cutlet" + ] + ) + def test_get_name(self, name): + ingredient = Ingredient(INGREDIENT_TYPE_SAUCE, name, 100) + assert ingredient.get_name() == name + + @pytest.mark.parametrize( + "price", + [ + 100, + 300 + ] + ) + def test_get_price(self, price): + ingredient = Ingredient(INGREDIENT_TYPE_SAUCE, "test", price) + assert ingredient.get_price() == price + \ No newline at end of file