Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Виртуальные окружения Python
.env
.envrc
.venv
env/
venv/
ENV/

# Кэш Python
__pycache__/
*.pyc

# Настройки IDE и редакторов
.idea/
.vscode/

# Системные файлы ОС
.DS_Store
Thumbs.db

# Кэш и отчёты тестирования
.pytest_cache/
.coverage
.coverage.*
htmlcov/

# Инструменты тестирования
.tox/
.nox/
.cache
.hypothesis/

# Артефакты сборки
dist/
build/
52 changes: 39 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,50 @@
## Задание 1: Юнит-тесты
# Задание 1: Юнит-тесты

### Автотесты для проверки программы, которая помогает заказать бургер в Stellar Burgers
## Автотесты для проверки программы заказа бургеров в Stellar Burgers

### Реализованные сценарии
В проекте реализованы юнит-тесты для проверки работы программы, которая помогает собрать и заказать бургер.

Созданы юнит-тесты, покрывающие классы `Bun`, `Burger`, `Ingredient`, `Database`
## Реализованные сценарии

Процент покрытия 100% (отчет: `htmlcov/index.html`)
Написаны тесты для следующих классов:

### Структура проекта
- `Bun`
- `Burger`
- `Ingredient`
- `Database`

- `praktikum` - пакет, содержащий код программы
- `tests` - пакет, содержащий тесты, разделенные по классам. Например, `bun_test.py`, `burger_test.py` и т.д.
В тестах используются:
- параметризация (`pytest.mark.parametrize`)
- моки (`unittest.mock`)

### Запуск автотестов
Тестовое покрытие: **78%**

**Установка зависимостей**
HTML-отчет о покрытии находится в файле:

> `$ pip install -r requirements.txt`
`htmlcov/index.html`

**Запуск автотестов и создание HTML-отчета о покрытии**
## Структура проекта

> `$ pytest --cov=praktikum --cov-report=html`
praktikum/ — основной код программы
tests/ — автотесты

Тесты разделены по классам:

- `test_bun.py`
- `test_burger.py`
- `test_ingredient.py`
- `test_database.py`

## Запуск автотестов

### Установка зависимостей

`pip install -r requirements.txt`

### Запуск тестов и генерация отчета о покрытии

`pytest --cov=praktikum --cov-report=html`

После выполнения отчёт можно открыть в браузере:

`htmlcov/index.html`
Empty file added praktikum/__init__.py
Empty file.
File renamed without changes.
1 change: 1 addition & 0 deletions burger.py → praktikum/burger.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ def __init__(self):

def set_buns(self, bun: Bun):
self.bun = bun


def add_ingredient(self, ingredient: Ingredient):
self.ingredients.append(ingredient)
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pytest==9.0.1
pytest-cov==7.0.0
41 changes: 41 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import sys
import os

sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))

import pytest
import praktikum.ingredient_types as ing_type


from unittest.mock import Mock
from praktikum.bun import Bun
from praktikum.ingredient import Ingredient
from praktikum.burger import Burger


@pytest.fixture
def bun():
mock_bun = Mock(spec_set=Bun)
mock_bun.get_name.return_value = 'black bun'
mock_bun.get_price.return_value = 100
return mock_bun

@pytest.fixture
def ingredient_filling():
mock_ingridient = Mock(spec_set=Ingredient)
mock_ingridient.get_name.return_value = 'cutlet'
mock_ingridient.get_price.return_value = 100
mock_ingridient.get_type.return_value = ing_type.INGREDIENT_TYPE_FILLING
return mock_ingridient

@pytest.fixture
def ingredient_sauce():
mock_ingridient = Mock(spec_set=Ingredient)
mock_ingridient.get_name.return_value = 'chili sauce'
mock_ingridient.get_price.return_value = 300
mock_ingridient.get_type.return_value = ing_type.INGREDIENT_TYPE_SAUCE
return mock_ingridient

@pytest.fixture
def burger():
return Burger()
26 changes: 26 additions & 0 deletions tests/data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from praktikum.ingredient_types import INGREDIENT_TYPE_FILLING, INGREDIENT_TYPE_SAUCE


BUN = [
('black bun', 100),
('white bun', 200),
('red bun', 300)
]

BUN_WITH_INDEX = [
(0, 'black bun', 100),
(1, 'white bun', 200),
(2, 'red bun', 300)
]

FILLING = [
(INGREDIENT_TYPE_FILLING, "cutlet", 100),
(INGREDIENT_TYPE_FILLING, "dinosaur", 200),
(INGREDIENT_TYPE_FILLING, "sausage", 300),
]

SAUCE = [
(INGREDIENT_TYPE_SAUCE, "hot sauce", 100),
(INGREDIENT_TYPE_SAUCE, "sour cream", 200),
(INGREDIENT_TYPE_SAUCE, "chili sauce", 300),
]
13 changes: 13 additions & 0 deletions tests/test_bun.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import pytest


from praktikum.bun import Bun
from tests.data import BUN

class TestBun:
@pytest.mark.parametrize('name, price', BUN)
def test_bun_getters(self, name, price):
bun = Bun(name, price)

assert bun.get_name() == name
assert bun.get_price() == price
44 changes: 44 additions & 0 deletions tests/test_burger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
class TestBurger:
def test_burger_initialization(self, burger):
assert burger.bun is None
assert burger.ingredients == []

def test_burger_set_buns(self, burger, bun):
burger.set_buns(bun)
assert burger.bun == bun

def test_burger_add_ingredient(self, burger, ingredient_filling):
burger.add_ingredient(ingredient_filling)
assert len(burger.ingredients) == 1
assert burger.ingredients[0] == ingredient_filling

def test_burger_remove_ingredient(self, burger, ingredient_filling):
burger.add_ingredient(ingredient_filling)
burger.remove_ingredient(0)
assert burger.ingredients == []

def test_burger_move_ingredient(self, burger, ingredient_filling, ingredient_sauce):
burger.add_ingredient(ingredient_filling)
burger.add_ingredient(ingredient_sauce)
burger.move_ingredient(0, 1)
assert burger.ingredients == [ingredient_sauce, ingredient_filling]

def test_burger_get_price(self,burger, bun, ingredient_filling, ingredient_sauce):
burger.set_buns(bun)
burger.add_ingredient(ingredient_filling)
burger.add_ingredient(ingredient_sauce)
assert burger.get_price() == 600

def test_get_receipt(self,burger, bun, ingredient_filling, ingredient_sauce):
burger.set_buns(bun)
burger.add_ingredient(ingredient_filling)
burger.add_ingredient(ingredient_sauce)
receipt = burger.get_receipt()
expected_receipt = (
"(==== black bun ====)\n"
"= filling cutlet =\n"
"= sauce chili sauce =\n"
"(==== black bun ====)\n"
"Price: 600"
)
assert receipt.replace("\n\n", "\n") == expected_receipt
45 changes: 45 additions & 0 deletions tests/test_database.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import pytest


from praktikum.database import Database
from praktikum.bun import Bun
from praktikum.ingredient import Ingredient
from tests.data import FILLING, SAUCE, BUN_WITH_INDEX


class TestDatabase:
def test_database_has_three_buns(self):
db = Database()
assert len(db.available_buns()) == 3

def test_database_has_six_ingredients(self):
db = Database()
assert len(db.available_ingredients()) == 6

@pytest.mark.parametrize("index, name, price", BUN_WITH_INDEX)
def test_available_buns_content(self, index, name, price):
db = Database()
buns = db.available_buns()
assert buns[index].get_name() == name
assert buns[index].get_price() == price

@pytest.mark.parametrize("ingredient_type, name, price", FILLING + SAUCE)
def test_available_ingredients_content(self, ingredient_type, name, price):
db = Database()
ingredients = db.available_ingredients()
assert any(
ingredient.get_type() == ingredient_type
and ingredient.get_name() == name
and ingredient.get_price() == price
for ingredient in ingredients
)

def test_database_returns_buns_as_bun_objects(self):
db = Database()
buns = db.available_buns()
assert all(isinstance(b, Bun) for b in buns)

def test_database_returns_ingredients_as_ingredient_objects(self):
db = Database()
ingredients = db.available_ingredients()
assert all(isinstance(i, Ingredient) for i in ingredients)
13 changes: 13 additions & 0 deletions tests/test_ingredient.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import pytest

from praktikum.ingredient import Ingredient
from tests.data import FILLING, SAUCE

class TestIngredient:
@pytest.mark.parametrize('ingredient_type, name, price', FILLING + SAUCE)
def test_ingredient_getters(self, 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