mirror of https://github.com/tiangolo/fastapi.git
✅ Add the `docs_src` directory to test coverage and update tests (#1904)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
This commit is contained in:
parent
29e7b31ee6
commit
fa2c750443
|
|
@ -235,7 +235,7 @@ And then we can require it from the *path operation function* as a dependency an
|
||||||
|
|
||||||
Then it would be very easy to provide a different settings object during testing by creating a dependency override for `get_settings`:
|
Then it would be very easy to provide a different settings object during testing by creating a dependency override for `get_settings`:
|
||||||
|
|
||||||
```Python hl_lines="8-9 12 21"
|
```Python hl_lines="9-10 13 21"
|
||||||
{!../../../docs_src/settings/app02/test_main.py!}
|
{!../../../docs_src/settings/app02/test_main.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -288,7 +288,7 @@ Reading a file from disk is normally a costly (slow) operation, so you probably
|
||||||
But every time we do:
|
But every time we do:
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
config.Settings()
|
Settings()
|
||||||
```
|
```
|
||||||
|
|
||||||
a new `Settings` object would be created, and at creation it would read the `.env` file again.
|
a new `Settings` object would be created, and at creation it would read the `.env` file again.
|
||||||
|
|
@ -297,7 +297,7 @@ If the dependency function was just like:
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
def get_settings():
|
def get_settings():
|
||||||
return config.Settings()
|
return Settings()
|
||||||
```
|
```
|
||||||
|
|
||||||
we would create that object for each request, and we would be reading the `.env` file for each request. ⚠️
|
we would create that object for each request, and we would be reading the `.env` file for each request. ⚠️
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
|
|
||||||
from . import config
|
from .config import settings
|
||||||
|
|
||||||
app = FastAPI()
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
@ -8,7 +8,7 @@ app = FastAPI()
|
||||||
@app.get("/info")
|
@app.get("/info")
|
||||||
async def info():
|
async def info():
|
||||||
return {
|
return {
|
||||||
"app_name": config.settings.app_name,
|
"app_name": settings.app_name,
|
||||||
"admin_email": config.settings.admin_email,
|
"admin_email": settings.admin_email,
|
||||||
"items_per_user": config.settings.items_per_user,
|
"items_per_user": settings.items_per_user,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,18 +2,18 @@ from functools import lru_cache
|
||||||
|
|
||||||
from fastapi import Depends, FastAPI
|
from fastapi import Depends, FastAPI
|
||||||
|
|
||||||
from . import config
|
from .config import Settings
|
||||||
|
|
||||||
app = FastAPI()
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
@lru_cache()
|
@lru_cache()
|
||||||
def get_settings():
|
def get_settings():
|
||||||
return config.Settings()
|
return Settings()
|
||||||
|
|
||||||
|
|
||||||
@app.get("/info")
|
@app.get("/info")
|
||||||
async def info(settings: config.Settings = Depends(get_settings)):
|
async def info(settings: Settings = Depends(get_settings)):
|
||||||
return {
|
return {
|
||||||
"app_name": settings.app_name,
|
"app_name": settings.app_name,
|
||||||
"admin_email": settings.admin_email,
|
"admin_email": settings.admin_email,
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,19 @@
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
|
|
||||||
from . import config, main
|
from .config import Settings
|
||||||
|
from .main import app, get_settings
|
||||||
|
|
||||||
client = TestClient(main.app)
|
client = TestClient(app)
|
||||||
|
|
||||||
|
|
||||||
def get_settings_override():
|
def get_settings_override():
|
||||||
return config.Settings(admin_email="testing_admin@example.com")
|
return Settings(admin_email="testing_admin@example.com")
|
||||||
|
|
||||||
|
|
||||||
main.app.dependency_overrides[main.get_settings] = get_settings_override
|
app.dependency_overrides[get_settings] = get_settings_override
|
||||||
|
|
||||||
|
|
||||||
def test_app():
|
def test_app():
|
||||||
|
|
||||||
response = client.get("/info")
|
response = client.get("/info")
|
||||||
data = response.json()
|
data = response.json()
|
||||||
assert data == {
|
assert data == {
|
||||||
|
|
|
||||||
|
|
@ -7,4 +7,4 @@ bash ./scripts/lint.sh
|
||||||
# Check README.md is up to date
|
# Check README.md is up to date
|
||||||
python ./scripts/docs.py verify-readme
|
python ./scripts/docs.py verify-readme
|
||||||
export PYTHONPATH=./docs_src
|
export PYTHONPATH=./docs_src
|
||||||
pytest --cov=fastapi --cov=tests --cov=docs/src --cov-report=term-missing --cov-report=xml tests ${@}
|
pytest --cov=fastapi --cov=tests --cov=docs_src --cov-report=term-missing:skip-covered --cov-report=xml tests ${@}
|
||||||
|
|
|
||||||
|
|
@ -359,6 +359,12 @@ no_jessica = {
|
||||||
("/users/foo", 422, no_jessica, {}),
|
("/users/foo", 422, no_jessica, {}),
|
||||||
("/users/me?token=jessica", 200, {"username": "fakecurrentuser"}, {}),
|
("/users/me?token=jessica", 200, {"username": "fakecurrentuser"}, {}),
|
||||||
("/users/me", 422, no_jessica, {}),
|
("/users/me", 422, no_jessica, {}),
|
||||||
|
(
|
||||||
|
"/users?token=monica",
|
||||||
|
400,
|
||||||
|
{"detail": "No Jessica token provided"},
|
||||||
|
{},
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"/items?token=jessica",
|
"/items?token=jessica",
|
||||||
200,
|
200,
|
||||||
|
|
@ -372,6 +378,12 @@ no_jessica = {
|
||||||
{"name": "Plumbus", "item_id": "plumbus"},
|
{"name": "Plumbus", "item_id": "plumbus"},
|
||||||
{"X-Token": "fake-super-secret-token"},
|
{"X-Token": "fake-super-secret-token"},
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"/items/bar?token=jessica",
|
||||||
|
404,
|
||||||
|
{"detail": "Item not found"},
|
||||||
|
{"X-Token": "fake-super-secret-token"},
|
||||||
|
),
|
||||||
("/items/plumbus", 422, no_jessica, {"X-Token": "fake-super-secret-token"}),
|
("/items/plumbus", 422, no_jessica, {"X-Token": "fake-super-secret-token"}),
|
||||||
(
|
(
|
||||||
"/items?token=jessica",
|
"/items?token=jessica",
|
||||||
|
|
|
||||||
|
|
@ -44,3 +44,10 @@ def test_disable_openapi(monkeypatch):
|
||||||
assert response.status_code == 404, response.text
|
assert response.status_code == 404, response.text
|
||||||
response = client.get("/redoc")
|
response = client.get("/redoc")
|
||||||
assert response.status_code == 404, response.text
|
assert response.status_code == 404, response.text
|
||||||
|
|
||||||
|
|
||||||
|
def test_root():
|
||||||
|
client = TestClient(tutorial001.app)
|
||||||
|
response = client.get("/")
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.json() == {"message": "Hello World"}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,17 @@
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
|
from pytest import MonkeyPatch
|
||||||
|
|
||||||
from docs_src.settings.app02 import main, test_main
|
from docs_src.settings.app02 import main, test_main
|
||||||
|
|
||||||
client = TestClient(main.app)
|
client = TestClient(main.app)
|
||||||
|
|
||||||
|
|
||||||
def test_setting_override():
|
def test_settings(monkeypatch: MonkeyPatch):
|
||||||
|
monkeypatch.setenv("ADMIN_EMAIL", "admin@example.com")
|
||||||
|
settings = main.get_settings()
|
||||||
|
assert settings.app_name == "Awesome API"
|
||||||
|
assert settings.items_per_user == 50
|
||||||
|
|
||||||
|
|
||||||
|
def test_override_settings():
|
||||||
test_main.test_app()
|
test_main.test_app()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
from docs_src.app_testing import test_main_b
|
||||||
|
|
||||||
|
|
||||||
|
def test_app():
|
||||||
|
test_main_b.test_create_existing_item()
|
||||||
|
test_main_b.test_create_item()
|
||||||
|
test_main_b.test_create_item_bad_token()
|
||||||
|
test_main_b.test_read_inexistent_item()
|
||||||
|
test_main_b.test_read_item()
|
||||||
|
test_main_b.test_read_item_bad_token()
|
||||||
|
|
@ -1,10 +1,15 @@
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
|
|
||||||
from docs_src.websockets.tutorial003 import app
|
from docs_src.websockets.tutorial003 import app, html
|
||||||
|
|
||||||
client = TestClient(app)
|
client = TestClient(app)
|
||||||
|
|
||||||
|
|
||||||
|
def test_get():
|
||||||
|
response = client.get("/")
|
||||||
|
assert response.text == html
|
||||||
|
|
||||||
|
|
||||||
def test_websocket_handle_disconnection():
|
def test_websocket_handle_disconnection():
|
||||||
with client.websocket_connect("/ws/1234") as connection, client.websocket_connect(
|
with client.websocket_connect("/ws/1234") as connection, client.websocket_connect(
|
||||||
"/ws/5678"
|
"/ws/5678"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue