Skip to content

Commit e4bf6cd

Browse files
authored
test: add tests (#4)
1 parent 80e8cc2 commit e4bf6cd

File tree

8 files changed

+93
-3
lines changed

8 files changed

+93
-3
lines changed

.github/workflows/python.yml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: Python CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
test:
11+
name: Test and Lint
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- name: 🧾 Checkout repository
16+
uses: actions/checkout@v4
17+
18+
- name: 🐍 Set up Python
19+
uses: actions/setup-python@v5
20+
with:
21+
python-version: '3.13'
22+
23+
- name: 📦 Install Poetry
24+
run: |
25+
pip install poetry
26+
poetry config virtualenvs.create false
27+
28+
- name: 📄 Install dependencies
29+
run: poetry install --no-interaction --no-root
30+
31+
- name: ✅ Run tests
32+
run: poetry run pytest -v
33+
34+
- name: 🧼 Check formatting
35+
run: |
36+
pip install black
37+
black --check .
38+
39+
- name: 🔍 Lint with ruff
40+
run: |
41+
pip install ruff
42+
ruff check .

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Built to showcase best practices in Python backend development and serve as a so
99
- 🔀 Routing with versioned endpoints
1010
- 📄 OpenAPI docs auto-generated (`/docs`, `/redoc`)
1111
- ✅ Data validation and typing with Pydantic v2
12-
- 🧪 Async-ready test setup with `pytest`, `httpx`, `pytest-asyncio` (in progress)
12+
- 🧪 Async-ready test setup with `pytest`, `httpx`, `pytest-asyncio`
1313
- 🐳 Minimal Docker support
1414
- 🧰 Designed as a reusable starter template
1515

app/api/users.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
from fastapi import APIRouter, HTTPException
1+
from fastapi import APIRouter
2+
23
from app.models.user import User, UserCreate
34
from app.services.user_service import save_user, get_all_users
45

app/main.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
import sys
33

44
from fastapi import FastAPI
5+
56
from app.api import users
67

7-
log_format = '%(asctime)s | %(levelname)-8s | %(name)-12s - %(message)s'
8+
log_format = "%(asctime)s | %(levelname)-8s | %(name)-12s - %(message)s"
89
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG, format=log_format)
910

1011
app = FastAPI(title="Python FastAPI Template", version="0.1.0")

tests/api/__init__.py

Whitespace-only changes.

tests/api/test_users.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import httpx
2+
import pytest
3+
4+
from app.main import app
5+
6+
7+
@pytest.mark.asyncio
8+
async def test_create_user():
9+
transport = httpx.ASGITransport(app=app)
10+
async with httpx.AsyncClient(transport=transport, base_url="http://test") as ac:
11+
response = await ac.post(
12+
"/api/v1/users/", json={"name": "Simone", "email": "[email protected]"}
13+
)
14+
assert response.status_code == 200
15+
data = response.json()
16+
assert data["name"] == "Simone"
17+
assert data["email"] == "[email protected]"
18+
19+
20+
@pytest.mark.asyncio
21+
async def test_get_users():
22+
transport = httpx.ASGITransport(app=app)
23+
async with httpx.AsyncClient(transport=transport, base_url="http://test") as ac:
24+
response = await ac.get("/api/v1/users/")
25+
assert response.status_code == 200
26+
data = response.json()
27+
assert isinstance(data, list)

tests/services/__init__.py

Whitespace-only changes.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import pytest
2+
3+
from app.models.user import UserCreate
4+
from app.services.user_service import save_user, get_all_users
5+
6+
7+
@pytest.mark.asyncio
8+
async def test_save_user():
9+
user = UserCreate(name="Simone", email="[email protected]")
10+
saved_user = await save_user(user)
11+
assert saved_user.name == "Simone"
12+
assert saved_user.email == "[email protected]"
13+
14+
15+
@pytest.mark.asyncio
16+
async def test_get_all_users_empty():
17+
users = await get_all_users()
18+
assert isinstance(users, list)
19+
assert len(users) > 0

0 commit comments

Comments
 (0)