Complete Todo application implementation

- Update database path configuration
- Add test script for API functionality
- Update README with testing instructions
- Add requests package to requirements

generated with BackendIM... (backend.im)
This commit is contained in:
Automated Action 2025-05-13 06:19:17 +00:00
parent e852047583
commit 6da81ed97c
4 changed files with 169 additions and 3 deletions

View File

@ -9,6 +9,7 @@ A simple Todo application built with FastAPI and SQLite.
- Database migrations with Alembic
- Health check endpoint
- OpenAPI documentation
- Test script for API functionality
## Project Structure
@ -32,6 +33,7 @@ todoapplication/
├── alembic.ini # Alembic configuration
├── main.py # Application entry point
├── requirements.txt # Python dependencies
├── test_api.py # API testing script
```
## API Endpoints
@ -81,3 +83,13 @@ Create a new migration:
```bash
alembic revision -m "your migration message"
```
### Testing
Run the API tests (make sure the server is running first):
```bash
python test_api.py
```
This will test all the CRUD operations for the Todo API.

View File

@ -1,15 +1,17 @@
from pydantic import BaseModel
from typing import Optional
from pathlib import Path
import os
class Settings(BaseModel):
API_V1_STR: str = "/api/v1"
PROJECT_NAME: str = "Todo API"
PROJECT_DESCRIPTION: str = "A simple Todo API built with FastAPI and SQLite"
VERSION: str = "0.1.0"
# Database settings
DB_DIR: Path = Path("/app") / "storage" / "db"
BASE_DIR: Path = Path(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
DB_DIR: Path = BASE_DIR / "storage" / "db"
SQLALCHEMY_DATABASE_URL: Optional[str] = None
class Config:

View File

@ -4,4 +4,5 @@ sqlalchemy==2.0.27
pydantic==2.5.3
alembic==1.12.1
python-dotenv==1.0.0
pathlib==1.0.1
pathlib==1.0.1
requests==2.31.0

151
test_api.py Normal file
View File

@ -0,0 +1,151 @@
#!/usr/bin/env python3
"""
Test script for the Todo API
This script tests all the CRUD operations for the Todo API
"""
import requests
import json
import sys
from typing import Dict, Any, Optional
BASE_URL = "http://localhost:8000/api/v1"
def print_success(message: str) -> None:
"""Print a success message in green color"""
print(f"\033[92m✓ {message}\033[0m")
def print_error(message: str) -> None:
"""Print an error message in red color"""
print(f"\033[91m✗ {message}\033[0m")
def print_info(message: str) -> None:
"""Print an info message in blue color"""
print(f"\033[94m• {message}\033[0m")
def test_health_endpoint() -> bool:
"""Test the health endpoint"""
print_info("Testing health endpoint...")
try:
response = requests.get("http://localhost:8000/health")
if response.status_code == 200:
data = response.json()
if data.get("status") == "healthy":
print_success("Health endpoint is working")
return True
else:
print_error(f"Health endpoint returned unexpected data: {data}")
return False
else:
print_error(f"Health endpoint returned status code {response.status_code}")
return False
except Exception as e:
print_error(f"Error testing health endpoint: {e}")
return False
def create_todo(title: str, description: Optional[str] = None, completed: bool = False) -> Dict[str, Any]:
"""Create a new todo and return the created todo data"""
print_info(f"Creating todo: {title}")
todo_data = {
"title": title,
"description": description,
"completed": completed
}
response = requests.post(f"{BASE_URL}/todos/", json=todo_data)
if response.status_code == 201:
todo = response.json()
print_success(f"Todo created with ID: {todo['id']}")
return todo
else:
print_error(f"Failed to create todo. Status code: {response.status_code}")
print_error(f"Response: {response.text}")
return {}
def get_todo(todo_id: int) -> Dict[str, Any]:
"""Get a specific todo by ID"""
print_info(f"Getting todo with ID: {todo_id}")
response = requests.get(f"{BASE_URL}/todos/{todo_id}")
if response.status_code == 200:
todo = response.json()
print_success(f"Got todo: {todo['title']}")
return todo
else:
print_error(f"Failed to get todo. Status code: {response.status_code}")
print_error(f"Response: {response.text}")
return {}
def get_all_todos() -> list:
"""Get all todos"""
print_info("Getting all todos")
response = requests.get(f"{BASE_URL}/todos/")
if response.status_code == 200:
todos = response.json()
print_success(f"Got {len(todos)} todos")
return todos
else:
print_error(f"Failed to get todos. Status code: {response.status_code}")
print_error(f"Response: {response.text}")
return []
def update_todo(todo_id: int, data: Dict[str, Any]) -> Dict[str, Any]:
"""Update a specific todo"""
print_info(f"Updating todo with ID: {todo_id}")
response = requests.put(f"{BASE_URL}/todos/{todo_id}", json=data)
if response.status_code == 200:
todo = response.json()
print_success(f"Updated todo: {todo['title']}")
return todo
else:
print_error(f"Failed to update todo. Status code: {response.status_code}")
print_error(f"Response: {response.text}")
return {}
def delete_todo(todo_id: int) -> bool:
"""Delete a specific todo"""
print_info(f"Deleting todo with ID: {todo_id}")
response = requests.delete(f"{BASE_URL}/todos/{todo_id}")
if response.status_code == 204:
print_success(f"Deleted todo with ID: {todo_id}")
return True
else:
print_error(f"Failed to delete todo. Status code: {response.status_code}")
print_error(f"Response: {response.text}")
return False
def run_tests() -> None:
"""Run all tests"""
print_info("Starting API tests")
# Test health endpoint
if not test_health_endpoint():
print_error("Health endpoint test failed. Make sure the server is running.")
sys.exit(1)
# Test creating a todo
todo = create_todo("Test Todo", "This is a test todo", False)
if not todo:
print_error("Failed to create todo. Stopping tests.")
sys.exit(1)
todo_id = todo["id"]
# Test getting a specific todo
get_todo(todo_id)
# Test getting all todos
get_all_todos()
# Test updating a todo
updated_todo = update_todo(todo_id, {"title": "Updated Test Todo", "completed": True})
if not updated_todo:
print_error("Failed to update todo.")
# Test deleting a todo
if not delete_todo(todo_id):
print_error("Failed to delete todo.")
print_info("All tests completed")
if __name__ == "__main__":
run_tests()