Skip to content

Commit e54ceb9

Browse files
Updates
1 parent 2ea920c commit e54ceb9

10 files changed

+632
-148
lines changed

app/models.py

+16-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,28 @@
11
from app.database import Base
2-
from sqlalchemy import TIMESTAMP, Column, String, Boolean
2+
from sqlalchemy import TIMESTAMP, Column, String, Boolean, Index
33
from sqlalchemy.sql import func
44
from fastapi_utils.guid_type import GUID, GUID_DEFAULT_SQLITE
55

66

77
class User(Base):
88
__tablename__ = "users"
9+
10+
# Primary key and GUID type
911
id = Column(GUID, primary_key=True, default=GUID_DEFAULT_SQLITE)
10-
first_name = Column(String, nullable=False)
11-
last_name = Column(String, nullable=False)
12-
address = Column(String, nullable=True)
12+
13+
# String types with appropriate non-null constraints
14+
first_name = Column(
15+
String(255), nullable=False, index=True
16+
) # Indexed for faster searches
17+
last_name = Column(
18+
String(255), nullable=False, index=True
19+
) # Indexed for faster searches
20+
address = Column(String(255), nullable=True)
21+
22+
# Boolean type with a default value
1323
activated = Column(Boolean, nullable=False, default=True)
24+
25+
# Timestamps with timezone support
1426
createdAt = Column(
1527
TIMESTAMP(timezone=True), nullable=False, server_default=func.now()
1628
)

app/schemas.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
from datetime import datetime
22
from typing import List
3-
from pydantic import BaseModel
3+
from pydantic import BaseModel, Field
44

55

66
class UserBaseSchema(BaseModel):
77
id: str | None = None
8-
first_name: str
9-
last_name: str
8+
first_name: str = Field(
9+
..., description="The first name of the user", example="John"
10+
)
11+
last_name: str = Field(..., description="The last name of the user", example="Doe")
1012
address: str | None = None
1113
activated: bool = False
1214
createdAt: datetime | None = None

poetry.lock

+480
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
[tool.poetry]
2+
name = "pytest-fastapi-crud-example"
3+
version = "0.1.0"
4+
description = "Example of testing a FastAPI CRUD API in Pytest"
5+
authors = ["ericsalesdeandrade <[email protected]>"]
6+
readme = "README.md"
7+
8+
[tool.poetry.dependencies]
9+
python = "^3.12"
10+
fastapi = "0.110.3"
11+
fastapi-utils = "^0.2.1"
12+
uvicorn = "^0.29.0"
13+
pydantic = "<2.0, >=1.7.4"
14+
httpx = "^0.27.0"
15+
16+
17+
[tool.poetry.group.test.dependencies]
18+
pytest = "^8.2.0"
19+
20+
[build-system]
21+
requires = ["poetry-core"]
22+
build-backend = "poetry.core.masonry.api"

pytest.ini

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
[pytest]
2-
log_cli=true
3-
log_level=INFO
2+
; log_cli=true
3+
; log_level=INFO
44
addopts = -p no:warnings

requirements.txt

-39
This file was deleted.

tests/conftest.py

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from fastapi.testclient import TestClient
2+
from app.main import app
3+
import uuid
4+
import pytest
5+
6+
7+
@pytest.fixture
8+
def test_client():
9+
yield TestClient(app)
10+
11+
12+
@pytest.fixture
13+
def user_id(scope="session"):
14+
return str(uuid.uuid4())
15+
16+
17+
@pytest.fixture
18+
def user_payload(user_id):
19+
return {
20+
"id": user_id,
21+
"first_name": "PLACEHOLDER",
22+
"last_name": "PLACEHOLDER",
23+
"address": "PLACEHOLDER",
24+
"createdAt": "2024-04-30T16:39:23",
25+
}

tests/test_crud_api.py

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
def test_root(test_client):
2+
response = test_client.get("/api/healthchecker")
3+
assert response.status_code == 200
4+
assert response.json() == {"message": "The API is LIVE!!"}
5+
6+
7+
def test_create_user_success(test_client, user_payload, user_id):
8+
response = test_client.post("/api/users/", json=user_payload)
9+
assert response.status_code == 201
10+
assert response.json() == {
11+
"Status": "Success",
12+
"User": {
13+
"id": user_id,
14+
"activated": False,
15+
"createdAt": "2024-04-30T16:39:23",
16+
"first_name": "PLACEHOLDER",
17+
"last_name": "PLACEHOLDER",
18+
"address": "PLACEHOLDER",
19+
"updatedAt": None,
20+
},
21+
}
22+
23+
24+
# def test_create_user_fail(test_client, user_payload, user_id):
25+
# response = test_client.post("/api/users/", json=user_payload)
26+
# assert response.status_code == 400
27+
# assert response.json() == {
28+
# "detail": "User with id: `16303002-876a-4f39-ad16-e715f151bab3` already exists"
29+
# }
30+
31+
32+
# def test_get_user(test_client):
33+
# response = test_client.get(f"/api/users/{user_id}")
34+
# assert response.status_code == 200
35+
# assert response.json() == {
36+
# "Status": "Success",
37+
# "User": {
38+
# "first_name": "PLACEHOLDER",
39+
# "last_name": "PLACEHOLDER",
40+
# "activated": False,
41+
# "createdAt": "2023-03-17T00:04:32",
42+
# "address": "PLACEHOLDER",
43+
# "id": user_id,
44+
# "updatedAt": None,
45+
# },
46+
# }
47+
48+
49+
# def test_update_user(test_client, sample_payload):
50+
# response = test_client.patch(f"/api/users/{user_id}", json=sample_payload)
51+
# assert response.status_code == 202
52+
# assert response.json() == {
53+
# "Status": "Success",
54+
# "User": {
55+
# "first_name": "PLACEHOLDER2",
56+
# "last_name": "PLACEHOLDER2",
57+
# "activated": True,
58+
# "createdAt": "2023-03-17T00:04:32",
59+
# "id": user_id,
60+
# "address": "PLACEHOLDER2",
61+
# "updatedAt": "2023-03-17T00:06:32",
62+
# },
63+
# }
64+
65+
66+
# def test_delete_user(test_client):
67+
# response = test_client.delete(f"/api/users/{user_id}")
68+
# assert response.status_code == 200
69+
# assert response.json() == {
70+
# "Status": "Success",
71+
# "Message": "User deleted successfully",
72+
# }
73+
74+
75+
# def test_get_user_not_found(test_client):
76+
# response = test_client.get(
77+
# f"/api/users/16303002-876a-4f39-ad16-e715f151bab3"
78+
# ) # GUID not in DB
79+
# assert response.status_code == 404
80+
# assert response.json() == {
81+
# "detail": "No User with this id: `16303002-876a-4f39-ad16-e715f151bab3` found"
82+
# }

tests/unit/__init__.py

Whitespace-only changes.

tests/unit/test_crud_api.py

-100
This file was deleted.

0 commit comments

Comments
 (0)