From 6cb4454b98aa194d41bee65f8626a0347551084d Mon Sep 17 00:00:00 2001
From: Areeb455 <141515705+Areeb455@users.noreply.github.com>
Date: Sat, 21 Feb 2026 22:13:15 +0000
Subject: [PATCH 1/4] docs: migrate testing tutorial from on_event to lifespan
---
docs/en/docs/advanced/async-tests.md | 2 +-
docs_src/app_testing/tutorial003_py310.py | 14 +++++++++-----
2 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/docs/en/docs/advanced/async-tests.md b/docs/en/docs/advanced/async-tests.md
index cefb1d1841..23745b5ce3 100644
--- a/docs/en/docs/advanced/async-tests.md
+++ b/docs/en/docs/advanced/async-tests.md
@@ -94,6 +94,6 @@ As the testing function is now asynchronous, you can now also call (and `await`)
/// tip
-If you encounter a `RuntimeError: Task attached to a different loop` when integrating asynchronous function calls in your tests (e.g. when using MongoDB's MotorClient), remember to instantiate objects that need an event loop only within async functions, e.g. an `@app.on_event("startup")` callback.
+If you encounter a `RuntimeError: Task attached to a different loop` when integrating asynchronous function calls in your tests (e.g. when using MongoDB's MotorClient), remember to instantiate objects that need an event loop only within async functions, for example, using a lifespan async context manager.
///
diff --git a/docs_src/app_testing/tutorial003_py310.py b/docs_src/app_testing/tutorial003_py310.py
index ca6b45ce03..45f6f678c6 100644
--- a/docs_src/app_testing/tutorial003_py310.py
+++ b/docs_src/app_testing/tutorial003_py310.py
@@ -1,15 +1,19 @@
+from contextlib import asynccontextmanager
+
from fastapi import FastAPI
from fastapi.testclient import TestClient
-app = FastAPI()
-
items = {}
-@app.on_event("startup")
-async def startup_event():
+@asynccontextmanager
+async def lifespan(app: FastAPI):
items["foo"] = {"name": "Fighters"}
items["bar"] = {"name": "Tenders"}
+ yield
+
+
+app = FastAPI(lifespan=lifespan)
@app.get("/items/{item_id}")
@@ -21,4 +25,4 @@ def test_read_items():
with TestClient(app) as client:
response = client.get("/items/foo")
assert response.status_code == 200
- assert response.json() == {"name": "Fighters"}
+ assert response.json() == {"name": "Fighters"}
\ No newline at end of file
From 473d68bd631459650f5b161988515e4badb3b2e3 Mon Sep 17 00:00:00 2001
From: "pre-commit-ci-lite[bot]"
<117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Date: Sat, 21 Feb 2026 22:18:51 +0000
Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=8E=A8=20Auto=20format?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
docs_src/app_testing/tutorial003_py310.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs_src/app_testing/tutorial003_py310.py b/docs_src/app_testing/tutorial003_py310.py
index 45f6f678c6..07bf7f2367 100644
--- a/docs_src/app_testing/tutorial003_py310.py
+++ b/docs_src/app_testing/tutorial003_py310.py
@@ -25,4 +25,4 @@ def test_read_items():
with TestClient(app) as client:
response = client.get("/items/foo")
assert response.status_code == 200
- assert response.json() == {"name": "Fighters"}
\ No newline at end of file
+ assert response.json() == {"name": "Fighters"}
From bde1624566c299afbc2b3c469198cd405e5c06c5 Mon Sep 17 00:00:00 2001
From: Areeb455 <141515705+Areeb455@users.noreply.github.com>
Date: Sat, 21 Feb 2026 23:01:38 +0000
Subject: [PATCH 3/4] docs: migrate to lifespan and update associated tests
---
docs_src/app_testing/tutorial003.py | 28 +++++++++++++++++++
.../test_testing/test_tutorial003.py | 5 ++--
2 files changed, 30 insertions(+), 3 deletions(-)
create mode 100644 docs_src/app_testing/tutorial003.py
diff --git a/docs_src/app_testing/tutorial003.py b/docs_src/app_testing/tutorial003.py
new file mode 100644
index 0000000000..45f6f678c6
--- /dev/null
+++ b/docs_src/app_testing/tutorial003.py
@@ -0,0 +1,28 @@
+from contextlib import asynccontextmanager
+
+from fastapi import FastAPI
+from fastapi.testclient import TestClient
+
+items = {}
+
+
+@asynccontextmanager
+async def lifespan(app: FastAPI):
+ items["foo"] = {"name": "Fighters"}
+ items["bar"] = {"name": "Tenders"}
+ yield
+
+
+app = FastAPI(lifespan=lifespan)
+
+
+@app.get("/items/{item_id}")
+async def read_items(item_id: str):
+ return items[item_id]
+
+
+def test_read_items():
+ with TestClient(app) as client:
+ response = client.get("/items/foo")
+ assert response.status_code == 200
+ assert response.json() == {"name": "Fighters"}
\ No newline at end of file
diff --git a/tests/test_tutorial/test_testing/test_tutorial003.py b/tests/test_tutorial/test_testing/test_tutorial003.py
index 196fc45559..bbadb296bb 100644
--- a/tests/test_tutorial/test_testing/test_tutorial003.py
+++ b/tests/test_tutorial/test_testing/test_tutorial003.py
@@ -1,7 +1,6 @@
import pytest
-
def test_main():
- with pytest.warns(DeprecationWarning):
- from docs_src.app_testing.tutorial003_py310 import test_read_items
+ from docs_src.app_testing.tutorial003_py310 import test_read_items
test_read_items()
+
From 5aa97a1776491347988100a7ee779cbb2f538bae Mon Sep 17 00:00:00 2001
From: Areeb455 <141515705+Areeb455@users.noreply.github.com>
Date: Sat, 21 Feb 2026 23:24:23 +0000
Subject: [PATCH 4/4] test: explicit imports for 100% coverage and mypy
compliance
---
check_params.py | 7 +++++++
docs_src/app_testing/tutorial003.py | 6 ++++--
.../test_tutorial/test_testing/test_tutorial003.py | 13 +++++++++----
3 files changed, 20 insertions(+), 6 deletions(-)
create mode 100644 check_params.py
diff --git a/check_params.py b/check_params.py
new file mode 100644
index 0000000000..df8719546d
--- /dev/null
+++ b/check_params.py
@@ -0,0 +1,7 @@
+from decimal import Decimal
+
+from fastapi import Query
+
+
+def create_item(price: Decimal = Query(..., max_digits=5, decimal_places=2)):
+ return {"price": price}
diff --git a/docs_src/app_testing/tutorial003.py b/docs_src/app_testing/tutorial003.py
index 45f6f678c6..3ff87cb2a7 100644
--- a/docs_src/app_testing/tutorial003.py
+++ b/docs_src/app_testing/tutorial003.py
@@ -1,9 +1,11 @@
from contextlib import asynccontextmanager
+from typing import Any
from fastapi import FastAPI
from fastapi.testclient import TestClient
-items = {}
+# Use typing.Dict for compatibility with older Python versions
+items: dict[str, Any] = {}
@asynccontextmanager
@@ -25,4 +27,4 @@ def test_read_items():
with TestClient(app) as client:
response = client.get("/items/foo")
assert response.status_code == 200
- assert response.json() == {"name": "Fighters"}
\ No newline at end of file
+ assert response.json() == {"name": "Fighters"}
diff --git a/tests/test_tutorial/test_testing/test_tutorial003.py b/tests/test_tutorial/test_testing/test_tutorial003.py
index bbadb296bb..b455bc949f 100644
--- a/tests/test_tutorial/test_testing/test_tutorial003.py
+++ b/tests/test_tutorial/test_testing/test_tutorial003.py
@@ -1,6 +1,11 @@
-import pytest
+from docs_src.app_testing import tutorial003, tutorial003_py310
-def test_main():
- from docs_src.app_testing.tutorial003_py310 import test_read_items
- test_read_items()
+def test_tutorial003():
+ # This covers the base version (tutorial003.py)
+ tutorial003.test_read_items()
+
+
+def test_tutorial003_py310():
+ # This covers the modern version (tutorial003_py310.py)
+ tutorial003_py310.test_read_items()