diff --git a/7project/backend/docker-compose.test.yml b/7project/backend/docker-compose.test.yml new file mode 100644 index 0000000..51d876b --- /dev/null +++ b/7project/backend/docker-compose.test.yml @@ -0,0 +1,20 @@ +version: "3.9" +services: + mariadb: + image: mariadb:11.4 + container_name: test-mariadb + environment: + MARIADB_ROOT_PASSWORD: rootpw + MARIADB_DATABASE: group_project + MARIADB_USER: appuser + MARIADB_PASSWORD: apppass + ports: + - "3307:3306" # host:container (use 3307 on host to avoid conflicts) + healthcheck: + test: ["CMD", "mariadb-admin", "ping", "-h", "127.0.0.1", "-u", "root", "-prootpw", "--silent"] + interval: 5s + timeout: 2s + retries: 20 + # Truly ephemeral, fast storage (removed when container stops) + tmpfs: + - /var/lib/mysql diff --git a/7project/backend/test-with-ephemeral-mariadb.sh b/7project/backend/test-with-ephemeral-mariadb.sh new file mode 100644 index 0000000..650edd2 --- /dev/null +++ b/7project/backend/test-with-ephemeral-mariadb.sh @@ -0,0 +1,76 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Run tests against a disposable local MariaDB on host port 3307 using Docker Compose. +# Requirements: Docker, docker compose plugin, Python, Alembic, pytest. +# Usage: +# chmod +x ./test-with-ephemeral-mariadb.sh +# ./test-with-ephemeral-mariadb.sh +# +# This script will: +# 1) Start a MariaDB 11.4 container (ephemeral storage, port 3307) +# 2) Wait until it's healthy +# 3) Export env vars expected by the app (DATABASE_URL etc.) +# 4) Run Alembic migrations +# 5) Run pytest +# 6) Tear everything down (containers and tmpfs data) + +COMPOSE_FILE="docker-compose.test.yml" +SERVICE_NAME="mariadb" +CONTAINER_NAME="test-mariadb" + +if ! command -v docker >/dev/null 2>&1; then + echo "Docker is required but not found in PATH" >&2 + exit 1 +fi +if ! docker compose version >/dev/null 2>&1; then + echo "Docker Compose V2 plugin is required (docker compose)" >&2 + exit 1 +fi + +# Bring up the DB +echo "Starting MariaDB (port 3307) with docker compose..." +docker compose -f "$COMPOSE_FILE" up -d + +# Ensure we clean up on exit +cleanup() { + echo "\nTearing down docker compose stack..." + docker compose -f "$COMPOSE_FILE" down -v || true +} +trap cleanup EXIT + +# Wait for healthy container +echo -n "Waiting for MariaDB to become healthy" +for i in {1..60}; do + status=$(docker inspect -f '{{.State.Health.Status}}' "$CONTAINER_NAME" 2>/dev/null || echo "") + if [ "$status" = "healthy" ]; then + echo " -> healthy" + break + fi + echo -n "." + sleep 1 + if [ $i -eq 60 ]; then + echo "\nMariaDB did not become healthy in time" >&2 + exit 1 + fi +done + +# Export env vars for the app/tests (match app/core/db.py expectations) +export MARIADB_HOST=127.0.0.1 +export MARIADB_PORT=3307 +export MARIADB_DB=group_project +export MARIADB_USER=appuser +export MARIADB_PASSWORD=apppass +export DATABASE_URL="mysql+asyncmy://$MARIADB_USER:$MARIADB_PASSWORD@$MARIADB_HOST:$MARIADB_PORT/$MARIADB_DB" +export PYTEST_RUN_CONFIG="True" + +# Run Alembic migrations then tests +pushd . >/dev/null + echo "Running Alembic migrations..." + alembic upgrade head + + echo "Running pytest..." + pytest "$@" +popd >/dev/null + +# Cleanup handled by trap