Python API template with an hexagonal architecture using:

The repository can be found there: github.com/aurelien-clu/template-python-fast-api

Layout

.
├── Makefile
├── pyproject.toml
├── src
│   ├── api                 <= API routes
│   │   └── health.py
│   │
│   ├── config              <= defaults + values from environment
│   │   └── server.py
│   │
│   ├── infra/              <= repositories, caches, etc.
│   │
│   ├── svc                 <= logic exposed by API routes
│   │  └── health.py
│   │
│   ├── app.py
│   ├── container.py        <= "registry" of dependencies to inject
│   ├── errors.py
│   └── main.py
└── tests
    └── bdd
        ├── health.feature  <= Gherkin tests
        └── steps/          <= Gherkin steps implementations

How to reuse

git clone https://github.com/aurelien-clu/template-python-fast-api <your-project>

Efficient test writing

Using Behavior Driven Development, it is easy to reuse parts of tests, alike querying an API endpoint, validating the response, etc.

Once a set of steps has been written (python code below) you are able to write many tests quickly using Gherkin language which ressemble natural language with the formalism of Given, When, Then.

// Gherkin test definition
Feature: Health
  Background:
    Given an API client
  Scenario: Health check: GET
    Given path: /
    When getting
    Then response code is 200
    And json response is "ok"

github.com/aurelien-clu/template-python-fast-api/tests/bdd/health.feature

# reusable steps across tests (repository hold few more)
@step("path: {path}")
def step_impl(context, path: str):
    context.request_path = path

@step("getting")
def step_impl(context):
    path = context.request_path
    headers = getattr(context, "request_headers", None)
    context.response = context.client.get(path, headers=headers)

@step("response code is {code}")
def step_impl(context, code: str):
    check = context.response.status_code == int(code)
    assert check

@step('json response is "{text}"')
def step_impl(context, text: str):
    check = context.response.json() == text
    assert check

github.com/aurelien-clu/template-python-fast-api/tests/bdd/steps