Kritim Yantra
Apr 14, 2025
FastAPI is a modern, fast (high-performance) web framework for building APIs with Python 3.7+ using standard Python type hints.
Test-Driven Development (TDD) is a software development approach where you write tests before writing the actual code. The cycle usually looks like this:
Let’s build a simple To-Do API using TDD with FastAPI.
fastapi-todo-tdd/
├── app/
│ ├── __init__.py
│ └── main.py
├── tests/
│ └── test_main.py
├── requirements.txt
└── README.md
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install fastapi uvicorn pytest httpx
Add these to requirements.txt
:
fastapi
uvicorn
pytest
httpx
Create a file tests/test_main.py
.
# tests/test_main.py
from fastapi.testclient import TestClient
from app.main import app
client = TestClient(app)
def test_read_root():
response = client.get("/")
assert response.status_code == 200
assert response.json() == {"message": "Welcome to the ToDo API"}
We haven't even created the /
endpoint yet. That’s the TDD way!
Create the file app/main.py
.
# app/main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"message": "Welcome to the ToDo API"}
pytest
✅ You should see:
1 passed in 0.XXs
Let’s allow users to add a to-do item.
Update tests/test_main.py
:
def test_create_todo():
response = client.post("/todos", json={"title": "Learn FastAPI"})
assert response.status_code == 201
assert response.json() == {
"id": 1,
"title": "Learn FastAPI"
}
🔴 Run the test now — it will fail (because the endpoint doesn’t exist yet). That’s expected!
Update app/main.py
:
from fastapi import FastAPI, status
from pydantic import BaseModel
app = FastAPI()
todos = [] # In-memory storage
id_counter = 1
class ToDo(BaseModel):
title: str
class ToDoResponse(ToDo):
id: int
@app.get("/")
def read_root():
return {"message": "Welcome to the ToDo API"}
@app.post("/todos", status_code=status.HTTP_201_CREATED, response_model=ToDoResponse)
def create_todo(todo: ToDo):
global id_counter
new_todo = {"id": id_counter, "title": todo.title}
todos.append(new_todo)
id_counter += 1
return new_todo
pytest
✅ Both tests should now pass:
2 passed in 0.XXs
Boom! You've just built a basic API endpoint using Test-Driven Development.
You can follow the same cycle for:
Each time, write a failing test, write the minimum code, then refactor.
Using TDD with FastAPI:
pytest
fixtures for setup/teardownDrop your comments or questions below. Happy coding!
No comments yet. Be the first to comment!
Please log in to post a comment:
Sign in with Google