PyTest-API: Populate OpenAPI Examples from Python Tests
PyTest-API is an ASGI middleware that populates OpenAPI-Specification examples from pytest functions.
Installation
poetry add --dev pytest-api
How to use it:
Starting with test_main.py file:
from .main import spec
@spec.describe(route="/behavior-example/")
def test_example_body(client):
"""
GIVEN behavior in body
WHEN example behavior endpoint is called with POST method
THEN response with status 200 and body OK is returned
"""
assert client.post(
"/behavior-example/", json={"name": "behavior"},
headers={"spec-example": test_example_body.id}
).json() == {"message": "OK"}
Impliment solution in /main.py file:
from fastapi import FastAPI
from pydantic import BaseModel
from pytest_api import ASGIMiddleware
app = FastAPI()
spec = ASGIMiddleware
app.add_middleware(spec)
app.openapi = spec.openapi_behaviors(app)
class Behavior(BaseModel):
name: str
@app.post("/behavior-example/")
async def example_body(behavior: Behavior):
return {"message": "OK"}
Run FastAPI app:
poetry run uvicorn test_app.main:app --reload
Open your browser to http://localhost:8000/docs#/ too find the doc string is populated into the description.
Implimentation Details
Under the hood the ASGIMiddleware uses the describe decorator to store the pytest function by its id:
def wrap_behavior(*args, **kwargs):
try:
BEHAVIORS[route]
except KeyError as e:
if route in e.args:
BEHAVIORS[route] = {str(id(func)): func}
BEHAVIORS[route][str(id(func))] = func
When pytest calls your API the SpecificationResponder is looking for the coresponding id in the headers of the request:
def handle_spec(self, headers):
behaviors = BEHAVIORS[self.path]
self.should_update_example = headers.get("spec-example", "") in behaviors
self.should_update_description = (
headers.get("spec-description", "") in behaviors
)
if self.should_update_example:
self.func = behaviors[headers.get("spec-example")]
elif self.should_update_description:
self.func = behaviors[headers.get("spec-description")]
This is possible thanks to python's first-class functions i.e. Closure_(computer_programming).
Release files for pytest-api 0.1.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pytest_api-0.1.4.tar.gz | 5.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pytest_api-0.1.4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 12.3 kB
Release files / pytest_api-0.1.4.tar.gz
| Download URL | pytest_api-0.1.4.tar.gz |
|---|---|
| Size | 5.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fa7ecdb1dc9677cb95b0d4e8449a277aa740f9d50df682be9253562386dc65e0
|
|
BLAKE2b-256 checksum How to use checksums |
fae2c820fdfbb151c73a18fb0638ca4aa4316086e2d3fa126fd4a0f1f7c2c3f6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.1.11 CPython/3.8.10 Linux/5.14.0-1034-oem
|
Release files / pytest_api-0.1.4-py3-none-any.whl
| Download URL | pytest_api-0.1.4-py3-none-any.whl |
|---|---|
| Size | 6.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
44357859f0fa021f10aef7865379dbc244cf99ccdd648ab5be47a9c496eeec84
|
|
BLAKE2b-256 checksum How to use checksums |
01768496680d9b1c69918df482a67e1af3156e9588a6c115fe60fdb098e8cd60
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.1.11 CPython/3.8.10 Linux/5.14.0-1034-oem
|