install:
- pip install flit
- - flit install
+ - flit install --symlink
script:
- bash scripts/test.sh
--- /dev/null
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.get("/")
+async def read_main():
+ return {"msg": "Hello World"}
--- /dev/null
+from starlette.testclient import TestClient
+
+from .main import app
+
+client = TestClient(app)
+
+
+def test_read_main():
+ response = client.get("/")
+ assert response.status_code == 200
+ assert response.json() == {"msg": "Hello World"}
--- /dev/null
+from fastapi import FastAPI
+from starlette.testclient import TestClient
+
+app = FastAPI()
+
+
+@app.get("/")
+async def read_main():
+ return {"msg": "Hello World"}
+
+
+client = TestClient(app)
+
+
+def test_read_main():
+ response = client.get("/")
+ assert response.status_code == 200
+ assert response.json() == {"msg": "Hello World"}
--- /dev/null
+from fastapi import FastAPI
+from starlette.testclient import TestClient
+from starlette.websockets import WebSocket
+
+app = FastAPI()
+
+
+@app.get("/")
+async def read_main():
+ return {"msg": "Hello World"}
+
+
+@app.websocket_route("/ws")
+async def websocket(websocket: WebSocket):
+ await websocket.accept()
+ await websocket.send_json({"msg": "Hello WebSocket"})
+ await websocket.close()
+
+
+def test_read_main():
+ client = TestClient(app)
+ response = client.get("/")
+ assert response.status_code == 200
+ assert response.json() == {"msg": "Hello World"}
+
+
+def test_websocket():
+ client = TestClient(app)
+ with client.websocket_connect("/ws") as websocket:
+ data = websocket.receive_json()
+ assert data == {"msg": "Hello WebSocket"}
--- /dev/null
+from fastapi import FastAPI
+from starlette.testclient import TestClient
+
+app = FastAPI()
+
+items = {}
+
+
+@app.on_event("startup")
+async def startup_event():
+ items["foo"] = {"name": "Fighters"}
+ items["bar"] = {"name": "Tenders"}
+
+
+@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"}
@app.get("/items/{item_id}")
-async def read_item(item_id: str):
+async def read_items(item_id: str):
return items[item_id]
It includes ways to authenticate using a "third party".
-That's what all the system with "login with Facebook, Google, Twitter, GitHub" use underneath.
+That's what all the systems with "login with Facebook, Google, Twitter, GitHub" use underneath.
### OAuth 1
--- /dev/null
+Thanks to <a href="https://www.starlette.io/testclient/" target="_blank">Starlette's TestClient</a>, testing **FastAPI** applications is easy and enjoyable.
+
+It is based on <a href="http://docs.python-requests.org" target="_blank">Requests</a>, so it's very familiar and intuitive.
+
+With it, you can use <a href="https://docs.pytest.org/" target="_blank">pytest</a> directly with **FastAPI**.
+
+## Using `TestClient`
+
+Import `TestClient` from `starlette.testclient`.
+
+Create a `TestClient` passing to it your **FastAPI**.
+
+Create functions with a name that starts with `test_` (this is standard `pytest` conventions).
+
+Use the `TestClient` object the same way as you do with `requests`.
+
+Write simple `assert` statements with the standard Python expressions that you need to check (again, standard `pytest`).
+
+```Python hl_lines="2 12 15 16 17 18"
+{!./src/app_testing/tutorial001.py!}
+```
+
+!!! tip
+ Notice that the testing functions are normal `def`, not `async def`.
+
+ And the calls to the client are also normal calls, not using `await`.
+
+ This allows you to use `pytest` directly without complications.
+
+
+## Separating tests
+
+In a real application, you probably would have your tests in a different file.
+
+And your **FastAPI** application might also be composed of several files/modules, etc.
+
+### **FastAPI** app file
+
+Let's say you have a file `main.py` with your **FastAPI** app:
+
+```Python
+{!./src/app_testing/main.py!}
+```
+
+### Testing file
+
+Then you could have a file `test_main.py` with your tests, and import your `app` from the `main` module (`main.py`):
+
+```Python
+{!./src/app_testing/test_main.py!}
+```
+
+## Testing WebSockets
+
+You can use the same `TestClient` to test WebSockets.
+
+For this, you use the `TestClient` in a `with` statement, connecting to the WebSocket:
+
+```Python hl_lines="27 28 29 30 31"
+{!./src/app_testing/tutorial002.py!}
+```
+
+## Testing Events, `startup` and `shutdown`
+
+When you need your event handlers (`startup` and `shutdown`) to run in your tests, you can use the `TestClient` with a `with` statement:
+
+```Python hl_lines="9 10 11 12 20 21 22 23 24"
+{!./src/app_testing/tutorial003.py!}
+```
- GraphQL: 'tutorial/graphql.md'
- WebSockets: 'tutorial/websockets.md'
- 'Events: startup - shutdown': 'tutorial/events.md'
+ - Testing: 'tutorial/testing.md'
- Debugging: 'tutorial/debugging.md'
- Extending OpenAPI: 'tutorial/extending-openapi.md'
- Concurrency and async / await: 'async.md'
},
},
},
- "summary": "Read Item Get",
- "operationId": "read_item_items__item_id__get",
+ "summary": "Read Items Get",
+ "operationId": "read_items_items__item_id__get",
"parameters": [
{
"required": True,
--- /dev/null
+from app_testing.test_main import client, test_read_main
+
+openapi_schema = {
+ "openapi": "3.0.2",
+ "info": {"title": "Fast API", "version": "0.1.0"},
+ "paths": {
+ "/": {
+ "get": {
+ "responses": {
+ "200": {
+ "description": "Successful Response",
+ "content": {"application/json": {"schema": {}}},
+ }
+ },
+ "summary": "Read Main Get",
+ "operationId": "read_main__get",
+ }
+ }
+ },
+}
+
+
+def test_openapi_schema():
+ response = client.get("/openapi.json")
+ assert response.status_code == 200
+ assert response.json() == openapi_schema
+
+
+def test_main():
+ test_read_main()
--- /dev/null
+from app_testing.tutorial001 import client, test_read_main
+
+openapi_schema = {
+ "openapi": "3.0.2",
+ "info": {"title": "Fast API", "version": "0.1.0"},
+ "paths": {
+ "/": {
+ "get": {
+ "responses": {
+ "200": {
+ "description": "Successful Response",
+ "content": {"application/json": {"schema": {}}},
+ }
+ },
+ "summary": "Read Main Get",
+ "operationId": "read_main__get",
+ }
+ }
+ },
+}
+
+
+def test_openapi_schema():
+ response = client.get("/openapi.json")
+ assert response.status_code == 200
+ assert response.json() == openapi_schema
+
+
+def test_main():
+ test_read_main()
--- /dev/null
+from app_testing.tutorial002 import test_read_main, test_websocket
+
+
+def test_main():
+ test_read_main()
+
+
+def test_ws():
+ test_websocket()
--- /dev/null
+from app_testing.tutorial003 import test_read_items
+
+
+def test_main():
+ test_read_items()