Need to learn FastAPI, well, fast? This repo shows you how to create unit tests for every tutorial example in the Official FastAPI documentation. The goal of this repo was two-fold, first to learn how to write REST API's in FastAPI and second, how to write unit tests for that REST API. The third goal was to learn modern Python programming, which includes typing, Pydantic, async/await and Python 3.9 features.
By Anthony Leotta
In this repo, I will work through the (Official FastAPI Tutorial](https://fastapi.tiangolo.com/tutorial/) by creating unit tests for each topic described. I may stray from the Official Tutorial to satisfy my own curiosity.
2/3/2022 Update:
Sometimes is pays to read the source to a project. In the case of FastAPI, every example in the online documentation can be found in a folder named "docs_src", and the unit tests for then are in "tests\test_tutorial". I learned alot from created my repo and creating all the unit test from scratch. After seeing the FastAPI tutorial code and pytest unit tests, I realized that using unit-tests as a learning tool really works. I think looking at code is one thing, but understanding code enough to be able to write unit tests solidifies the concepts on a whole different level. I am going to continue with this repo, even though I am basically doing the same thing that has already been done in FastAPI itself (and probably better).
-
Install httpie
http --verison
-
Follow Tony's Tricks to setup a fresh anaconda environments called fastapi39.
-
Activate Python Environment
conda activate fastapi39
-
Install package dependencies.
pip install -r requirements.txt
-
Test if uvicorn is installed correctly.
uvicorn --version
-
If it is, you will see something like this, the version number may vary:
Running uvicorn 0.15.0 with CPython 3.9.7 on Windows
-
Just run pytest, that's it.
pytest -vv --disable-warnings
-
To run just the fastapi_tutorial tests
pytest -vv --cov-report html --cov=fastapi_tutorial
-
To generate a coverage report of all tutorials and playgrounds
pytest -vv --cov-report html --cov=fastapi_tutorial pytest -vv --cov-report html --cov=pydantic_playground --cov-append pytest -vv --cov-report html --cov=pytest_playground --cov-append pytest -vv --cov-report html --cov=starlette_playground --cov-append pytest -vv --cov-report html --cov=typing_playground --cov-append
-
Which results in a coverage report of all unit tests.
- First Steps
- cd fastapi_tutorial
- cd ex01_first_steps
- uvicorn main:app --reload
- use httpie to make a APi request
http GET http://127.0.0.1:8000/
- Which will return
HTTP/1.1 200 OK content-length: 25 content-type: application/json date: Fri, 28 Jan 2022 18:04:18 GMT server: uvicorn { "message": "Hello World" }
- View Interactive API docs
- View Alternative Interactive API docs
- View OpenAPI Specification and JSON Schema
-
Add a debug launch configuration to .vscode\launch.json
{ "name": "ex01_first_steps", "type": "python", "request": "launch", "module": "uvicorn", "cwd": "${workspaceFolder}/fastapi_tutorial/ex01_first_steps", "args": [ "main:app", "--reload" ], "jinja": true }
-
Test route @app.post()
- make a POST Request
cat data.json | http POST http://127.0.0.1:8000/
- Which will return
{ "method": "POST", "request": { "email": "[email protected]", "name": "Anthony", "password": "123456" } }
- make a POST Request
-
Test route @app.put()
- make a PUT Request
cat data.json | http PUT http://127.0.0.1:8000/
- Which will return
{ "method": "PUT", "request": { "email": "[email protected]", "name": "Anthony", "password": "123456" } }
- make a PUT Request
-
Test route @app.delete()
- make a DELETE Request
cat data.json | http DELETE http://127.0.0.1:8000/
- Which will return
{ "method": "DELETE", "request": { "email": "[email protected]", "name": "Anthony", "password": "123456" } }
- make a DELETE Request
-
Test route @app.options()
- make a OPTIONS Request
http OPTIONS http://127.0.0.1:8000/
- make a OPTIONS Request
-
Which will return
{ "method": "OPTIONS" }
-
Test route @app.head()
- make a HEAD Request
http HEAD http://127.0.0.1:8000/
- make a HEAD Request
-
Which will return
{ "method": "HEAD" }
-
Test route @app.patch()
- make a PATCH Request
cat data.json | http PATCH http://127.0.0.1:8000/
- Which will return
{ "method": "PATCH", "request": { "email": "[email protected]", "name": "Anthony", "password": "123456" } }
- make a PATCH Request
-
Test route @app.trace()
- make a TRACE Request
http TRACE http://127.0.0.1:8000/
- Which will return
{ "method": "TRACE" }
- make a TRACE Request
- Path Parameters
- Running the unit tests
pytest -vv fastapi_tutorial\ex02_path_parameters\test_ex02_path_parameters.py
- Query Parameters
- Running the unit tests
pytest -vv fastapi_tutorial\ex03_query_parameters\test_ex03_query_parameters.py
- Request Body
- Running the unit tests
pytest -vv fastapi_tutorial\ex04_request_body\test_ex04_request_body.py
- Query Parameters and String Validations
- Running the unit tests
pytest -vv fastapi_tutorial\ex05_query_parameters_and_string_validations\test_ex05_query_parameters_and_string_validations.py
- Path Parameters and Numeric Validations
- Running the unit tests
pytest -vv fastapi_tutorial\ex06_path_parameters_and_numeric_validations\test_ex06_path_parameters_and_numeric_validations.py
- Body - Multiple Parameters
- Running the unit tests
pytest -vv fastapi_tutorial\ex07_body_multiple_parameters\test_ex07_body_multiple_parameters.py
- Body - Fields
- Running the unit tests
pytest -vv fastapi_tutorial\ex08_body_fields\test_ex08_body_fields.py
- Body - Nested Models
- Running the unit tests
pytest -vv fastapi_tutorial\ex09_body_nested_models\test_ex09_body_nested_models.py
- Declare Request Example Data
- There are no unit test for this section
- run server
- visit Docs
-
This is a deceptively deep section. FastAPI's abilities to use different datatypes relieve just how much the Python language itself is in flux. The differences between Python 3.5 to Python 3.11 are different enough to force the FastAPI documentation to include in some cases three versions of the same FastAPi code.
-
I am going with Python 3.6 and 3.9. Python 3.10 and 3.11 seem stable enough but I cab only fight some many battles at once. I will upgrade this repro to Python 3.11 or 3.12 when the time seems rights.
-
Running the unit tests
pytest -vv fastapi_tutorial\ex11_extra_data_types\test_ex11_extra_data_types.py
- Cookie Parameters
- Running the unit tests
pytest -vv fastapi_tutorial\ex12_cookie_parameters\test_ex12_cookie_parameters.py
-
Running the unit tests
pytest -vv fastapi_tutorial\ex13_header_parameters\test_ex13_header_parameters.py
-
Since the TestClient does not allow for duplicate headers to be sent, I will test using httpie.
http GET http://127.0.0.1:8000/items2/ X-Token:foo
-
Returns
HTTP/1.1 200 OK content-length: 26 content-type: application/json date: Wed, 02 Feb 2022 14:43:43 GMT server: uvicorn { "X-Token values": [ "foo" ] }
-
Sendc duplicate header
http GET http://127.0.0.1:8000/items2/ X-Token:foo X-Token:bar
-
Returns
HTTP/1.1 200 OK content-length: 32 content-type: application/json date: Wed, 02 Feb 2022 14:44:57 GMT server: uvicorn { "X-Token values": [ "foo", "bar" ] }
-
To fix this bug the fastapi39\Lib\site-packages\requests\models.py lines 446 to 455 need to look for either a dictionary or a list, because dictionaries do not allow duplicate keys.
def prepare_headers(self, headers): """Prepares the given HTTP headers.""" self.headers = CaseInsensitiveDict() if headers: for header in headers.items(): # Raise exception on invalid header value. check_header_validity(header) name, value = header self.headers[to_native_string(name)] = value
- Response Model
- Running the unit tests
pytest -vv fastapi_tutorial\ex14_response_model\test_ex14_response_model.py
- Extra Models
- Running the unit tests
pytest -vv fastapi_tutorial\ex15_extra_models\test_ex15_extra_models.py
- Response Status Code
- Running the unit tests
pytest -vv fastapi_tutorial\ex16_response_status_code\test_ex16_response_status_codes.py
- Form Data
- Running the unit tests
pytest -vv fastapi_tutorial\ex17_form_data\test_ex17_form_data.py
- Request Files
- To run unit tests.
pytest -vv fastapi_tutorial\ex18_request_files\test_ex18_request_files.py
- MIME Types
- Pick the ex18_request_files launch target from the VS Code Debug Launch drop-down
- The launch configuration is shown below:
{ "name": "ex18_request_files", "type": "python", "request": "launch", "module": "uvicorn", "cwd": "${workspaceFolder}/fastapi_tutorial/ex18_request_files", "args": ["main:app", "--reload"], "jinja": true }
- Click the green triangle launch button
- The FastAPI server should start up and messages will appear in the terminal.
- Test with httpie
- cd to the images folder
- http --form POST http://localhost:8000/files/ file@PIA09258_callisto.jpg
- I set a break point on line 9 of
- The response was
HTTP/1.1 200 OK content-length: 19 content-type: application/json date: Wed, 02 Feb 2022 22:49:47 GMT server: uvicorn { "file_size": 10603 }
- Test with a web browser
`. Open a browser to http://localhost:8000/one
- The webpage to upload one file should be displayed.
- I have downloaded some public domain images from publicdomainreview.org in a folder names "images", select one of those or your own file to upload. Also some NASA images from NASA are there.
- upload a file
- It works!
-
Test with httpie
- cd to the images folder
- http --form POST http://localhost:8000/files/many/ files@PIA09258_callisto.jpg files@PIA00600_modest.jpg
- I set a break point on line 9 of
- The response was
HTTP/1.1 200 OK content-length: 28 content-type: application/json date: Thu, 03 Feb 2022 01:53:54 GMT server: uvicorn { "file_sizes": [ 10603, 31793 ] }
- It worked!
-
Test with a web browser
- Open a browser to http://localhost:8000/many/
- The webpage to upload one file should be displayed.
- Select files to be uploaded
- It works!
{"file_sizes":[60080,59073,57081,48237]}
-
To run unit tests.
pytest -vv fastapi_tutorial\ex19_request_forms_and_files\test_ex19_request_forms_and_files.py
-
To run unit tests.
pytest -vv fastapi_tutorial\ex20_handling_errors\test_ex20_handling_errors.py pytest -vv fastapi_tutorial\ex20_handling_errors\test_ex20_handling_errors_plain_exception.py
-
To run unit tests.
pytest -vv fastapi_tutorial\ex21_path_operation_configuration\test_ex21_path_operation_configuration.py
-
To view API docs
- Start server
- I use a VS Code Launch Configuration named: ex21_path_operation_configuration
- View Interactive API docs
- View Alternative Interactive API docs
- View OpenAPI Specification and JSON Schema
- Start server
-
To run unit tests.
pytest -vv fastapi_tutorial\ex22_json_compatible_encoder\test_ex22_json_compatible_encoder.py
-
To run unit tests.
pytest -vv fastapi_tutorial\ex23_body_updates\test_ex23_body_updates.py
-
To run unit tests.
pytest -vv fastapi_tutorial\ex26_middleware\test_ex26_middleware.py
-
To run unit tests.
pytest -vv fastapi_tutorial\ex27_cors\test_ex27_cors.py
-
To run unit tests.
pytest -vv fastapi_tutorial\ex28_sql_databases\test_ex28_sql_databases.py
-
The unit tests will create a test.db file, which needs to be deleted after each run.
- I need to add a tear down that deletes this file
- for sqlite this means delete it
- I need to add a tear down that deletes this file
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- coming soon
- Awesome FastAPI | | Curated list of awesome lists | Project-Awesome.org
- mjhea0/awesome-fastapi: A curated list of awesome things related to FastAPI
- Kludex/awesome-fastapi-projects: List of FastAPI projects!
-
ChristopherGS/ultimate-fastapi-tutorial: The Ultimate FastAPI Tutorial
-
How to Set Up a HTML App with FastAPI, Jinja, Forms & Templates
-
rogulski.it | My experience with FastAPI and async database connection
-
api - Is it possible to use FastAPI with Django? - Stack Overflow
-
Developing and Testing an Asynchronous API with FastAPI and Pytest | TestDriven.io
-
Serving a Machine Learning Model with FastAPI and Docker | TestDriven.io
-
Test-Driven Development with FastAPI and Docker - Docker Config | TestDriven.io
-
Test-Driven Development with FastAPI and Docker - Structure | TestDriven.io
-
FastAPI — the spiffy way beyond flask! – Towards AI — The Best of Tech, Science, and Engineering
-
Modern APIs with FastAPI and Python Online Course - [Talk Python Training]
-
Testing FastAPI Endpoints with Docker and Pytest | JeffAstor.com
-
fastapi-react vs full-stack-fastapi-postgresql - compare differences and reviews? | LibHunt
-
FastAPI language translations I18n Step by Step - MyBlueLinux.COM
-
Build The Next Generation Of Python Web Applications With FastAPI - The Python Podcast
-
FastAPI and React Full-stack Application: How to send emails using FastAPI-mail library - YouTube
-
Intro to FastAPI - The Best Way to Create APIs in Python? - YouTube
-
Let's Build a Fast, Modern Python API with FastAPI - YouTube
-
Python Asynchronous Programming - AsyncIO & Async/Await - YouTube
- Introducing the FARM stack - FastAPI, React, & MongoDB - PyCascades 2021
- Learn the FARM Stack! (FastAPI, React, MongoDB)
- Introducing FARM Stack - FastAPI, React, and MongoDB
- Build Full-Stack Projects with FARM stack
- FARM STACK [ FastAPI +React+ mongoDB] - DEV Community
- FARM Stack Course - FastAPI, React, MongoDB - YouTube
- FastAPI and React Full-stack Application: Introduction to Project - YouTube
- Building the Poll App From Django Tutorial With FastAPI And React
- Developing a Single Page App with FastAPI and React | TestDriven.io
- Consuming a FastAPI Backend from a React Frontend | JeffAstor.com
- Stubbing Out and Documenting FastAPI, VueJS 3 and Docker Workflow
- vuejs3 - Using Bootstrap 5 with Vue 3 - Stack Overflow
- Developing a Single Page App with FastAPI and Vue.js | TestDriven.io
- sdairs/vue3-fastapi-oath2-jwt-demo: This is a Demo project to show how to do OAth2 token auth with FastAPI to Vue3 frontend with JWT (with Postgres)
- Vue JS, FastAPI website tutorial (with Apache, certs, environments) - YouTube
- A full stack boilerplate for FastAPI
- 🚀 Cookiecutter Template for FastAPI + React Projects. Using PostgreSQL, SQLAlchemy, and Docker | PythonRepo
- Buuntu/fastapi-react: 🚀 Cookiecutter Template for FastAPI + React Projects. Using PostgreSQL, SQLAlchemy, and Docker
- isakbosman/full-stack-fastapi-react-postgres-boilerplate: A full-stack cookiecutter boilerplate using React, Redux, frontend, a FastAPI backend with a PostgreSql database
- fastapi-admin/fastapi-admin: A fast admin dashboard based on FastAPI and TortoiseORM with tabler ui, inspired by Django admin
- ultimate-fastapi-tutorial/part-9-async at main · ChristopherGS/ultimate-fastapi-tutorial
- talkpython/modern-apis-with-fastapi: Course demos and handouts for our Modern APIs with FastAPI course.
- testdrivenio/fastapi-tdd-docker: Test-Driven Development with FastAPI and Docker
- tiangolo/fastapi: FastAPI framework, high performance, easy to learn, fast to code, ready for production
- fastapi/pyproject.toml at master · tiangolo/fastapi
- The Future of FastAPI and Pydantic is Bright - DEV Community
- Create custom datatypes using Pydantic module in Python - GeeksforGeeks
- FastAPI with Async SQLAlchemy, SQLModel, and Alembic | TestDriven.io
- Build an async python service with FastAPI & SQLAlchemy | by Michael Azimov | Towards Data Science
- FastAPI + SQLAlchemy: Asynchronous IO and Back Pressure | peterspython.com
- Best approach for async SQLAlchemy in FastAPI : FastAPI
- async/await FastAPI with SQLAlchemy test