|
| 1 | +#!/usr/bin/env python3 |
| 2 | +import argparse |
| 3 | +import os |
| 4 | +import signal |
| 5 | +import subprocess |
| 6 | +import sys |
| 7 | +from pathlib import Path |
| 8 | + |
| 9 | +# Constants |
| 10 | +SCRIPT_DIR = Path(__file__).resolve().parent |
| 11 | +PROJECT_ROOT = SCRIPT_DIR.parent |
| 12 | +COMPOSE_FILE = SCRIPT_DIR / "docker-compose.test.yml" |
| 13 | + |
| 14 | +DSNS = { |
| 15 | + "postgres": "postgresql+asyncpg://a2a:a2a_password@localhost:5432/a2a_test", |
| 16 | + "mysql": "mysql+aiomysql://a2a:a2a_password@localhost:3306/a2a_test", |
| 17 | +} |
| 18 | + |
| 19 | +def run_command(command, cwd=None, env=None, check=True): |
| 20 | + """Runs a shell command.""" |
| 21 | + try: |
| 22 | + subprocess.run(command, cwd=cwd, env=env, check=check) |
| 23 | + except subprocess.CalledProcessError as e: |
| 24 | + sys.exit(e.returncode) |
| 25 | + |
| 26 | +def stop_databases(): |
| 27 | + """Stops the test databases.""" |
| 28 | + print("Stopping test databases...") |
| 29 | + run_command( |
| 30 | + ["docker", "compose", "-f", str(COMPOSE_FILE), "down"], |
| 31 | + check=False |
| 32 | + ) |
| 33 | + |
| 34 | +def main(): |
| 35 | + parser = argparse.ArgumentParser( |
| 36 | + description="Run integration tests with Docker databases.", |
| 37 | + add_help=False # handle help manually to pass args to pytest |
| 38 | + ) |
| 39 | + parser.add_argument("--debug", action="store_true", help="Start DBs and exit without running tests") |
| 40 | + parser.add_argument("--stop", action="store_true", help="Stop the databases and exit") |
| 41 | + parser.add_argument("--postgres", action="store_true", help="Use PostgreSQL") |
| 42 | + parser.add_argument("--mysql", action="store_true", help="Use MySQL") |
| 43 | + parser.add_argument("--help", action="store_true", help="Show this help message") |
| 44 | + |
| 45 | + # Parse known args, leave the rest for pytest |
| 46 | + args, pytest_args = parser.parse_known_args() |
| 47 | + |
| 48 | + if args.help: |
| 49 | + parser.print_help() |
| 50 | + print("\nAny other arguments will be passed to pytest.") |
| 51 | + sys.exit(0) |
| 52 | + |
| 53 | + if args.stop: |
| 54 | + stop_databases() |
| 55 | + sys.exit(0) |
| 56 | + |
| 57 | + # Determine which services to run |
| 58 | + services = [] |
| 59 | + if args.postgres: |
| 60 | + services.append("postgres") |
| 61 | + if args.mysql: |
| 62 | + services.append("mysql") |
| 63 | + |
| 64 | + # Default to both if neither is specified |
| 65 | + if not services: |
| 66 | + services = ["postgres", "mysql"] |
| 67 | + |
| 68 | + print(f"Starting/Verifying databases: {', '.join(services)}...") |
| 69 | + run_command( |
| 70 | + ["docker", "compose", "-f", str(COMPOSE_FILE), "up", "-d", "--wait"] + services |
| 71 | + ) |
| 72 | + |
| 73 | + # Prepare environment variables |
| 74 | + env = os.environ.copy() |
| 75 | + for service in services: |
| 76 | + if service == "postgres": |
| 77 | + env["POSTGRES_TEST_DSN"] = DSNS["postgres"] |
| 78 | + elif service == "mysql": |
| 79 | + env["MYSQL_TEST_DSN"] = DSNS["mysql"] |
| 80 | + |
| 81 | + if args.debug: |
| 82 | + print("-" * 51) |
| 83 | + print("Debug mode enabled. Databases are running.") |
| 84 | + print("You can connect to them using the following DSNs:") |
| 85 | + if "postgres" in services: |
| 86 | + print(f"Postgres: {DSNS['postgres']}") |
| 87 | + if "mysql" in services: |
| 88 | + print(f"MySQL: {DSNS['mysql']}") |
| 89 | + print("-" * 51) |
| 90 | + print(f"Run {sys.argv[0]} --stop to shut them down.") |
| 91 | + sys.exit(0) |
| 92 | + |
| 93 | + # Register cleanup on normal exit or signals |
| 94 | + def signal_handler(sig, frame): |
| 95 | + stop_databases() |
| 96 | + sys.exit(0) |
| 97 | + |
| 98 | + signal.signal(signal.SIGINT, signal_handler) |
| 99 | + signal.signal(signal.SIGTERM, signal_handler) |
| 100 | + |
| 101 | + try: |
| 102 | + print("Running integration tests...") |
| 103 | + |
| 104 | + test_files = [ |
| 105 | + "tests/server/tasks/test_database_task_store.py", |
| 106 | + "tests/server/tasks/test_database_push_notification_config_store.py", |
| 107 | + ] |
| 108 | + |
| 109 | + cmd = ["uv", "run", "--extra", "all", "pytest", "-v"] + test_files + pytest_args |
| 110 | + run_command(cmd, cwd=PROJECT_ROOT, env=env) |
| 111 | + |
| 112 | + finally: |
| 113 | + # Always cleanup unless in debug mode (which exits earlier) |
| 114 | + stop_databases() |
| 115 | + |
| 116 | +if __name__ == "__main__": |
| 117 | + main() |
0 commit comments