Skip to content

Latest commit

 

History

History
865 lines (641 loc) · 31.4 KB

README.md

File metadata and controls

865 lines (641 loc) · 31.4 KB

fastapi un-official tutorial

TL;DR

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.

Preface

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).

Setup

  1. Install httpie

    http --verison
    
  2. Follow Tony's Tricks to setup a fresh anaconda environments called fastapi39.

  3. Activate Python Environment

    conda activate fastapi39
    
  4. Install package dependencies.

    pip install -r requirements.txt
    
  5. Test if uvicorn is installed correctly.

    uvicorn --version
    
  6. 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
    

Running the Tests using Pytest

  1. Just run pytest, that's it.

    pytest -vv --disable-warnings
    
  2. To run just the fastapi_tutorial tests

    pytest -vv --cov-report html  --cov=fastapi_tutorial
    
  3. 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
    
  4. Which results in a coverage report of all unit tests.

Testing each server with httpie

  1. First Steps
  2. cd fastapi_tutorial
  3. cd ex01_first_steps
  4. uvicorn main:app --reload
  5. use httpie to make a APi request
    http GET http://127.0.0.1:8000/
    
  6. 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"
    }
    
  7. View Interactive API docs
  8. View Alternative Interactive API docs
  9. View OpenAPI Specification and JSON Schema

Testing using VS Code Interactive Step Debugger

  1. 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
    }
    
  2. Test route @app.post()

    1. make a POST Request
      cat data.json | http POST http://127.0.0.1:8000/
      
    2. Which will return
      {
          "method": "POST",
          "request": {
              "email": "[email protected]",
              "name": "Anthony",
              "password": "123456"
          }
      }
      
  3. Test route @app.put()

    1. make a PUT Request
      cat data.json | http PUT http://127.0.0.1:8000/
      
    2. Which will return
      {
          "method": "PUT",
          "request": {
              "email": "[email protected]",
              "name": "Anthony",
              "password": "123456"
          }
      }
      
  4. Test route @app.delete()

    1. make a DELETE Request
      cat data.json | http DELETE http://127.0.0.1:8000/
      
    2. Which will return
      {
          "method": "DELETE",
          "request": {
              "email": "[email protected]",
              "name": "Anthony",
              "password": "123456"
          }
      }
      
  5. Test route @app.options()

    1. make a OPTIONS Request
      http OPTIONS http://127.0.0.1:8000/
      
  6. Which will return

    {
        "method": "OPTIONS"
    }
    
  7. Test route @app.head()

    1. make a HEAD Request
      http HEAD http://127.0.0.1:8000/
      
  8. Which will return

    {
        "method": "HEAD"
    }
    
  9. Test route @app.patch()

    1. make a PATCH Request
      cat data.json | http PATCH http://127.0.0.1:8000/
      
    2. Which will return
      {
          "method": "PATCH",
          "request": {
              "email": "[email protected]",
              "name": "Anthony",
              "password": "123456"
          }
      }
      
  10. Test route @app.trace()

    1. make a TRACE Request
      http TRACE http://127.0.0.1:8000/
      
    2. Which will return
      {
          "method": "TRACE"
      }
      

ex02_path_parameters

  1. Path Parameters
  2. Running the unit tests
    pytest -vv fastapi_tutorial\ex02_path_parameters\test_ex02_path_parameters.py
    

ex03_query_parameters

  1. Query Parameters
  2. Running the unit tests
    pytest -vv fastapi_tutorial\ex03_query_parameters\test_ex03_query_parameters.py
    

ex04_request_body

  1. Request Body
  2. Running the unit tests
    pytest -vv fastapi_tutorial\ex04_request_body\test_ex04_request_body.py
    

ex05_query_parameters_and_string_validations

  1. Query Parameters and String Validations
  2. Running the unit tests
    pytest -vv fastapi_tutorial\ex05_query_parameters_and_string_validations\test_ex05_query_parameters_and_string_validations.py
    

ex06_path_parameters_and_numeric_validations

  1. Path Parameters and Numeric Validations
  2. Running the unit tests
    pytest -vv fastapi_tutorial\ex06_path_parameters_and_numeric_validations\test_ex06_path_parameters_and_numeric_validations.py
    

ex07_body_multiple_parameters

  1. Body - Multiple Parameters
  2. Running the unit tests
    pytest -vv fastapi_tutorial\ex07_body_multiple_parameters\test_ex07_body_multiple_parameters.py
    

ex08_body_fields

  1. Body - Fields
  2. Running the unit tests
    pytest -vv fastapi_tutorial\ex08_body_fields\test_ex08_body_fields.py
    

ex09_body_nested_models

  1. Body - Nested Models
  2. Running the unit tests
    pytest -vv fastapi_tutorial\ex09_body_nested_models\test_ex09_body_nested_models.py
    

ex10_declare_request_example_data

  1. Declare Request Example Data
  2. There are no unit test for this section
  3. run server
  4. visit Docs Example JSON

ex11_extra_data_types

  1. Extra Data Types

  2. 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.

  3. 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.

  4. Extra Data Types

  5. Running the unit tests

    pytest -vv fastapi_tutorial\ex11_extra_data_types\test_ex11_extra_data_types.py
    

ex12_cookie_parameters

  1. Cookie Parameters
  2. Running the unit tests
    pytest -vv fastapi_tutorial\ex12_cookie_parameters\test_ex12_cookie_parameters.py
    

ex13_header_parameters

  1. Header Parameters

  2. Running the unit tests

    pytest -vv fastapi_tutorial\ex13_header_parameters\test_ex13_header_parameters.py
    
  3. 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
    
  4. 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"
        ]
    }
    
  5. Sendc duplicate header

    http GET http://127.0.0.1:8000/items2/ X-Token:foo X-Token:bar
    
  6. 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"
        ]
    }
    
  7. 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
    

ex14_response_model

  1. Response Model
  2. Running the unit tests
    pytest -vv fastapi_tutorial\ex14_response_model\test_ex14_response_model.py
    

ex15_extra_models

  1. Extra Models
  2. Running the unit tests
    pytest -vv fastapi_tutorial\ex15_extra_models\test_ex15_extra_models.py
    

ex16_response_status_code

  1. Response Status Code
  2. Running the unit tests
    pytest -vv fastapi_tutorial\ex16_response_status_code\test_ex16_response_status_codes.py
    

ex17_form_data

  1. Form Data
  2. Running the unit tests
    pytest -vv fastapi_tutorial\ex17_form_data\test_ex17_form_data.py
    

ex18_request_files

  1. Request Files
  2. To run unit tests.
    pytest -vv fastapi_tutorial\ex18_request_files\test_ex18_request_files.py
    
  3. MIME Types

Test Upload One File at a Time

  1. Pick the ex18_request_files launch target from the VS Code Debug Launch drop-down Select the ex18_request_files debug launch configuration
  2. 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
    }
    
  3. Click the green triangle launch button Launch
  4. The FastAPI server should start up and messages will appear in the terminal. FastAPI Server Running
  5. Test with httpie
    1. cd to the images folder
    2. http --form POST http://localhost:8000/files/ file@PIA09258_callisto.jpg
    3. I set a break point on line 9 of STopped at a break point
    4. 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
    }
    
    1. This matches the file size. File Properties Dialog
    2. It worked!
  6. Test with a web browser `. Open a browser to http://localhost:8000/one
    1. The webpage to upload one file should be displayed. Upload one file at a time
    2. 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.
    3. upload a file upload a file
    4. It works! Upload One File Success

Upload Multiple Files

  1. Test with httpie

    1. cd to the images folder
    2. http --form POST http://localhost:8000/files/many/ files@PIA09258_callisto.jpg files@PIA00600_modest.jpg
    3. I set a break point on line 9 of STopped at a break point
    4. 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
          ]
      }
      
    5. It worked!
  2. Test with a web browser

    1. Open a browser to http://localhost:8000/many/
    2. The webpage to upload one file should be displayed. Upload multiple files at once.
    3. Select files to be uploaded
    4. It works!
      {"file_sizes":[60080,59073,57081,48237]}
      

ex19_request_forms_and_files

  1. Request Forms and Files

  2. To run unit tests.

    pytest -vv fastapi_tutorial\ex19_request_forms_and_files\test_ex19_request_forms_and_files.py
    

ex20_handling_errors

  1. Handling Errors

  2. 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
    

ex21_path_operation_configuration

  1. Path Operation Configuration

  2. To run unit tests.

    pytest -vv fastapi_tutorial\ex21_path_operation_configuration\test_ex21_path_operation_configuration.py
    
  3. To view API docs

    1. Start server
      1. I use a VS Code Launch Configuration named: ex21_path_operation_configuration
    2. View Interactive API docs
    3. View Alternative Interactive API docs
    4. View OpenAPI Specification and JSON Schema

ex22_json_compatible_encoder

  1. JSON Compatible Encoder

  2. To run unit tests.

    pytest -vv fastapi_tutorial\ex22_json_compatible_encoder\test_ex22_json_compatible_encoder.py
    

ex23_body_updates

  1. Body - Updates

  2. To run unit tests.

    pytest -vv fastapi_tutorial\ex23_body_updates\test_ex23_body_updates.py
    

ex26_middleware

  1. Middleware

  2. To run unit tests.

    pytest -vv fastapi_tutorial\ex26_middleware\test_ex26_middleware.py
    

ex27_cors

  1. CORS (Cross-Origin Resource Sharing)

  2. To run unit tests.

    pytest -vv fastapi_tutorial\ex27_cors\test_ex27_cors.py
    

ex28_sql_databases

  1. SQL (Relational) Databases

  2. To run unit tests.

    pytest -vv fastapi_tutorial\ex28_sql_databases\test_ex28_sql_databases.py
    
  3. 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

ex29_bigger_applications_multiple_files

  1. coming soon

ex30_background_tasks

  1. coming soon

ex31_metadata_and_docs_urls

  1. coming soon

ex32_static_files

  1. coming soon

ex33_testing

  1. coming soon

ex34_debugging

  1. coming soon

ex35_advanced_user_guide_intro

  1. coming soon

ex36_advanced_path_operation_advanced_configuration

  1. coming soon

ex37_advanced_additional_status_codes

  1. coming soon

ex38_advanced_return_a_response_directly

  1. coming soon

ex39_advanced_custom_response_html_stream_file_others

  1. coming soon

ex40_additional_responses_in_openapi

  1. coming soon

ex41_advanced_response_cookies

  1. coming soon

ex42_advanced_response_headers

  1. coming soon

ex43_advanced_response_change_status_code

  1. coming soon

ex44_advanced_advanced_dependencies

  1. coming soon

ex45_advanced_security

  1. coming soon

ex46_advanced_using_the_request_directly

  1. coming soon

ex47_advanced_using_dataclasses

  1. coming soon

ex48_advanced_middleware

  1. coming soon

ex49_advanced_sql_relational_databases_with_peewee

  1. coming soon

ex50_advanced_async_sql_relational_databases

  1. coming soon

ex51_advanced_nosql_distributed__big_data_databases

  1. coming soon

ex52_advanced_sub_applications_mounts

  1. coming soon

ex53_advanced_behind_a_proxy

  1. coming soon

ex54_advanced_templates

  1. coming soon

ex55_advanced_graphql

  1. coming soon

ex56_advanced_websockets

  1. coming soon

ex57_advanced_events_startup_shutdown

  1. coming soon

ex58_advanced_custom_request_and_apiroute_class

  1. coming soon

ex59_advanced_testing_websockets

  1. coming soon

ex61_advanced_testing_dependencies_with_overrides

  1. coming soon

ex62_advanced_testing_a_database

  1. coming soon

ex63_advanced_async_tests

  1. coming soon

ex64_advanced_settings_and_environment_variables

  1. coming soon

ex65_advanced_conditional_openapi

  1. coming soon

ex66_advanced_extending_openapi

  1. coming soon

ex67_advanced_openapi_callbacks

  1. coming soon

ex68_advanced_including_wsgi_flask_django_others

  1. coming soon

ex69_concurrency_and_async_await

  1. coming soon

Resources

Awesome List

  1. Awesome FastAPI | | Curated list of awesome lists | Project-Awesome.org
  2. mjhea0/awesome-fastapi: A curated list of awesome things related to FastAPI
  3. Kludex/awesome-fastapi-projects: List of FastAPI projects!

Tutorials

  1. ChristopherGS/ultimate-fastapi-tutorial: The Ultimate FastAPI Tutorial

  2. calmcode - learn Fastapi calmly - Hello World

  3. The Ultimate FastAPI Tutorial Part 1 - Basic API Endpoints

  4. Serving Static Files in FastAPI - DEV Community

  5. How to Set Up a HTML App with FastAPI, Jinja, Forms & Templates

  6. FastAPI

  7. Async SQL (Relational) Databases - FastAPI

  8. Async Tests - FastAPI

  9. Project Generation - Template - FastAPI

  10. Dependencies - First Steps - FastAPI

  11. First Steps - FastAPI

  12. Testing - FastAPI

  13. Create a Full Stack Note-Taking App with Python, FastAPI, Docker and PostgreSQL | by Abhishek | Python in Plain English

  14. Full stack, modern web application generator. Using FastAPI, PostgreSQL as database, Docker, automatic HTTPS and more. | PythonRepo

  15. Using FastAPI to Build Python Web APIs – Real Python

  16. rogulski.it | My experience with FastAPI and async database connection

  17. api - Is it possible to use FastAPI with Django? - Stack Overflow

  18. Developing and Testing an Asynchronous API with FastAPI and Pytest | TestDriven.io

  19. FastAPI Tutorials | TestDriven.io

  20. Serving a Machine Learning Model with FastAPI and Docker | TestDriven.io

  21. Test-Driven Development with FastAPI and Docker - Docker Config | TestDriven.io

  22. Test-Driven Development with FastAPI and Docker - Structure | TestDriven.io

  23. FastAPI — the spiffy way beyond flask! – Towards AI — The Best of Tech, Science, and Engineering

  24. How To Build and Deploy a Machine Learning Model with FastAPI | by Dario Radečić | Towards Data Science

  25. Modern APIs with FastAPI and Python Online Course - [Talk Python Training]

  26. FastAPI vs Flask | Is FastAPI Right Replacement for Flask?

  27. FastapiTutorial

  28. Testing FastAPI Endpoints with Docker and Pytest | JeffAstor.com

  29. fastapi-react vs full-stack-fastapi-postgresql - compare differences and reviews? | LibHunt

  30. FastAPI language translations I18n Step by Step - MyBlueLinux.COM

  31. Build The Next Generation Of Python Web Applications With FastAPI - The Python Podcast

  32. FastAPI and React Full-stack Application: How to send emails using FastAPI-mail library - YouTube

  33. Getting Started With Python FastAPI - YouTube

  34. Asyncio: Understanding Async / Await in Python - YouTube

  35. Intro to FastAPI - The Best Way to Create APIs in Python? - YouTube

  36. Let's Build a Fast, Modern Python API with FastAPI - YouTube

  37. Python Asynchronous Programming - AsyncIO & Async/Await - YouTube

FARM Stack (Full Stack with React and MongoDB)

  1. Introducing the FARM stack - FastAPI, React, & MongoDB - PyCascades 2021
  2. Learn the FARM Stack! (FastAPI, React, MongoDB)
  3. Introducing FARM Stack - FastAPI, React, and MongoDB
  4. Build Full-Stack Projects with FARM stack
  5. FARM STACK [ FastAPI +React+ mongoDB] - DEV Community
  6. FARM Stack Course - FastAPI, React, MongoDB - YouTube

Full Stack with React

  1. FastAPI and React Full-stack Application: Introduction to Project - YouTube
  2. Building the Poll App From Django Tutorial With FastAPI And React
  3. Developing a Single Page App with FastAPI and React | TestDriven.io
  4. Consuming a FastAPI Backend from a React Frontend | JeffAstor.com

Full Stack with Vue

  1. Stubbing Out and Documenting FastAPI, VueJS 3 and Docker Workflow
  2. vuejs3 - Using Bootstrap 5 with Vue 3 - Stack Overflow
  3. Developing a Single Page App with FastAPI and Vue.js | TestDriven.io
  4. 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)
  5. Vue JS, FastAPI website tutorial (with Apache, certs, environments) - YouTube

Starter Projects

  1. A full stack boilerplate for FastAPI
  2. 🚀 Cookiecutter Template for FastAPI + React Projects. Using PostgreSQL, SQLAlchemy, and Docker | PythonRepo
  3. Buuntu/fastapi-react: 🚀 Cookiecutter Template for FastAPI + React Projects. Using PostgreSQL, SQLAlchemy, and Docker
  4. isakbosman/full-stack-fastapi-react-postgres-boilerplate: A full-stack cookiecutter boilerplate using React, Redux, frontend, a FastAPI backend with a PostgreSql database
  5. fastapi-admin/fastapi-admin: A fast admin dashboard based on FastAPI and TortoiseORM with tabler ui, inspired by Django admin

Github Projects

  1. ultimate-fastapi-tutorial/part-9-async at main · ChristopherGS/ultimate-fastapi-tutorial
  2. talkpython/modern-apis-with-fastapi: Course demos and handouts for our Modern APIs with FastAPI course.
  3. testdrivenio/fastapi-tdd-docker: Test-Driven Development with FastAPI and Docker
  4. tiangolo/fastapi: FastAPI framework, high performance, easy to learn, fast to code, ready for production
  5. fastapi/pyproject.toml at master · tiangolo/fastapi

Pydantic

  1. The Future of FastAPI and Pydantic is Bright - DEV Community
  2. Create custom datatypes using Pydantic module in Python - GeeksforGeeks

Code Generator

  1. GitHub - koxudaxi/fastapi-code-generator: This code generator creates FastAPI app from an openapi file.

SQLAlchemy

  1. FastAPI with Async SQLAlchemy, SQLModel, and Alembic | TestDriven.io
  2. Build an async python service with FastAPI & SQLAlchemy | by Michael Azimov | Towards Data Science
  3. FastAPI + SQLAlchemy: Asynchronous IO and Back Pressure | peterspython.com
  4. Best approach for async SQLAlchemy in FastAPI : FastAPI
  5. async/await FastAPI with SQLAlchemy test

GraphQL

  1. GraphQL - FastAPI
  2. Developing an API with FastAPI and GraphQL | TestDriven.io