Testing Applications Built with other Frameworks like Flask, FastAPI, or Django
With Testcontainers, you can test any app running in a container.
Using the testcontainer_image
pytest fixture,
you can build a Docker image with Dockerfile from a current working directory.
Then, you can use the built Docker image ID to start a new container.
To learn how to create your new Testcontainers, see the previous guide - Creating new Testcontainers.
Below are examples of running Flask, FastAPI, and Django applications with Testcontainers. The specific framework doesn't matter as long as it runs in a container.
Flask example
src/flask_app.py
import os
from flask import Flask, Response, jsonify
app = Flask(__name__)
@app.route("/hello")
def hello_api() -> Response:
greet = os.getenv("GREET", "stranger")
return jsonify({"message": f"Hello from Flask, {greet}!"})
@app.route("/health")
def healthcheck_api() -> Response:
return jsonify({"status": "ok"})
tests/test_flask_app.py
from typing import Generator
import pytest
import requests
from tomodachi_testcontainers import DockerContainer, WebContainer
class FlaskContainer(WebContainer):
def __init__(self, image: str) -> None:
super().__init__(
image=image,
internal_port=5000,
http_healthcheck_path="/health",
)
def log_message_on_container_start(self) -> str:
return f"Flask web app: http://localhost:{self.edge_port}"
@pytest.fixture(scope="session")
def flask_container(testcontainer_image: str) -> Generator[DockerContainer, None, None]:
with (
FlaskContainer(testcontainer_image)
.with_env("GREET", "Testcontainers")
.with_command("flask --app creating_testcontainers/flask_app.py run --host 0.0.0.0 --port 5000")
) as container:
yield container
def test_greetings_from_flask(flask_container: FlaskContainer) -> None:
base_url = flask_container.get_external_url()
response = requests.get(f"{base_url}/hello", timeout=10)
assert response.json() == {"message": "Hello from Flask, Testcontainers!"}
FastAPI example
src/fastapi_app.py
import os
from fastapi import FastAPI
app = FastAPI()
@app.get("/hello")
async def hello_api() -> dict:
greet = os.getenv("GREET", "stranger")
return {"message": f"Hello from FastAPI, {greet}!"}
@app.get("/health")
async def healthcheck_api() -> dict:
return {"status": "ok"}
tests/test_fastapi_app.py
from typing import Generator
import pytest
import requests
from tomodachi_testcontainers import DockerContainer, WebContainer
class FastAPIContainer(WebContainer):
def __init__(self, image: str) -> None:
super().__init__(
image,
internal_port=8000,
http_healthcheck_path="/health",
)
def log_message_on_container_start(self) -> str:
return f"FastAPI web app: http://localhost:{self.edge_port}"
@pytest.fixture(scope="session")
def fastapi_container(testcontainer_image: str) -> Generator[DockerContainer, None, None]:
with (
FastAPIContainer(testcontainer_image)
.with_env("GREET", "Testcontainers")
.with_command("uvicorn creating_testcontainers.fastapi_app:app --host 0.0.0.0 --port 8000")
) as container:
yield container
def test_greetings_from_fastapi(fastapi_container: FastAPIContainer) -> None:
base_url = fastapi_container.get_external_url()
response = requests.get(f"{base_url}/hello", timeout=10)
assert response.json() == {"message": "Hello from FastAPI, Testcontainers!"}
Django example
src/django_app/django_app/views.py
import os
from django.http import HttpRequest, JsonResponse
def hello_api(request: HttpRequest) -> JsonResponse:
greet = os.getenv("GREET", "stranger")
return JsonResponse({"message": f"Hello from Django, {greet}!"})
def healthcheck_api(request: HttpRequest) -> JsonResponse:
return JsonResponse({"status": "ok"})
tests/test_django_app.py
from typing import Generator
import pytest
import requests
from tomodachi_testcontainers import DockerContainer, WebContainer
class DjangoContainer(WebContainer):
def __init__(self, image: str) -> None:
super().__init__(
image=image,
internal_port=8000,
http_healthcheck_path="/health",
)
def log_message_on_container_start(self) -> str:
return f"Django web app: http://localhost:{self.edge_port}"
@pytest.fixture(scope="session")
def django_container(testcontainer_image: str) -> Generator[DockerContainer, None, None]:
with (
DjangoContainer(testcontainer_image)
.with_env("GREET", "Testcontainers")
.with_command("python creating_testcontainers/django_app/manage.py runserver 0.0.0.0:8000")
) as container:
yield container
def test_greetings_from_django(django_container: DjangoContainer) -> None:
base_url = django_container.get_external_url()
response = requests.get(f"{base_url}/hello", timeout=10)
assert response.json() == {"message": "Hello from Django, Testcontainers!"}