Skip to content

Commit d478e95

Browse files
committed
Add unit tests
1 parent 9e9775e commit d478e95

File tree

9 files changed

+177
-2
lines changed

9 files changed

+177
-2
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from http import HTTPStatus
2+
3+
from fastapi import HTTPException
4+
5+
6+
class BusinessError(HTTPException):
7+
def __init__(
8+
self,
9+
detail: str | None = None,
10+
status_code: int = HTTPStatus.UNPROCESSABLE_ENTITY,
11+
) -> None:
12+
super().__init__(status_code=status_code, detail=detail)

domain/src/domain/entities/product.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from pydantic import Field
44

5+
from common.business_error import BusinessError
56
from domain.entity import Entity
67

78

@@ -11,3 +12,11 @@ class Product(Entity):
1112
price: Decimal = Field(gt=Decimal("0.0"))
1213
is_discontinued: bool
1314
discontinuation_reason: str | None = None
15+
16+
def discontinue(self, discontinuation_reason: str | None = None) -> None:
17+
if self.is_discontinued:
18+
error_message = "The product is already discontinued"
19+
raise BusinessError(error_message)
20+
21+
self.is_discontinued = True
22+
self.discontinuation_reason = discontinuation_reason

domain/tests/unit/test_product.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,18 @@
11
import pytest
22

3+
from common.business_error import BusinessError
4+
from test_utils.builders.domain.entities.product_builder import ProductBuilder
5+
36

47
@pytest.mark.unit
58
class TestProduct:
6-
def test_create_product(self) -> None:
7-
assert 1 == 1
9+
def test_discontinue_product(self) -> None:
10+
product = ProductBuilder().build()
11+
12+
product.discontinue()
13+
14+
def test_fail_when_discontinuing_discontinued_product(self) -> None:
15+
product = ProductBuilder().discontinued().build()
16+
17+
with pytest.raises(BusinessError):
18+
product.discontinue()

pyproject.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ dev = [
1515
"api",
1616
"jupyter==1.1.1",
1717
"pyright[nodejs]==1.1.400",
18+
"pytest==8.3.5",
19+
"pytest-asyncio==0.26.0",
20+
"pytest-cov==6.1.1",
21+
"pytest-mock==3.14.0",
1822
"ruff==0.11.9",
1923
"test-utils",
2024
"transcriber",
@@ -54,4 +58,5 @@ ignore = [
5458

5559
[tool.pytest.ini_options]
5660
asyncio_mode = "auto"
61+
asyncio_default_fixture_loop_scope = "function"
5762
markers = ["unit: Unit tests", "integration: Integration tests"]

test_utils/src/test_utils/builders/__init__.py

Whitespace-only changes.

test_utils/src/test_utils/builders/domain/__init__.py

Whitespace-only changes.

test_utils/src/test_utils/builders/domain/entities/__init__.py

Whitespace-only changes.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from decimal import Decimal
2+
from typing import Self
3+
4+
from domain.entities.product import Product
5+
6+
7+
class ProductBuilder:
8+
def __init__(self) -> None:
9+
self.is_discontinued = False
10+
11+
def build(self) -> Product:
12+
return Product(
13+
name="Table",
14+
description="Description",
15+
price=Decimal("10.0"),
16+
is_discontinued=self.is_discontinued,
17+
)
18+
19+
def discontinued(self) -> Self:
20+
self.is_discontinued = True
21+
return self

uv.lock

Lines changed: 117 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)