PayrollManagementSystem/scripts/run_isolated_tests.py

52 lines
2.3 KiB
Python
Raw Normal View History

"""使用唯一的本地测试库运行迁移和集成测试,绝不清理原业务库。"""
import os
import argparse
import re
import secrets
import subprocess
import sys
from pathlib import Path
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--reuse-database')
parser.add_argument('--migration-roundtrip', action='store_true')
parsed, test_args = parser.parse_known_args()
if parsed.reuse_database and not re.fullmatch(r'payroll_test_[0-9a-f]{12}', parsed.reuse_database):
raise SystemExit('只允许复用本运行器创建的隔离测试库')
root = Path(__file__).resolve().parents[1]
python = root / "backend/.venv-workbench/Scripts/python.exe"
if not python.exists():
python = Path(sys.executable)
suffix = secrets.token_hex(6)
database, username = parsed.reuse_database or "payroll_test_" + suffix, "pytest_" + suffix
password = secrets.token_urlsafe(30)
sql = ("" if parsed.reuse_database else f"CREATE DATABASE `{database}` CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; ") + f"CREATE USER '{username}'@'%' IDENTIFIED BY '{password}'; GRANT ALL PRIVILEGES ON `{database}`.* TO '{username}'@'%';"
setup = subprocess.run(
["docker", "exec", "-i", "ys-mysql-dev", "sh", "-c", 'export MYSQL_PWD="$MYSQL_ROOT_PASSWORD"; exec mysql -uroot'],
input=sql.encode(), capture_output=True,
)
if setup.returncode:
raise SystemExit("隔离库创建失败,未执行迁移或测试")
env = os.environ | {
"MYSQL_DATABASE": database, "MYSQL_USER": username, "MYSQL_PASSWORD": password,
"PAYROLL_TEST_DATABASE": database, "REDIS_DB": "15", "PYTHONIOENCODING": "utf-8",
}
print("独立测试库:" + database, flush=True)
commands = [["-m", "alembic", "upgrade", "head"]]
if parsed.migration_roundtrip:
commands += [["-m", "alembic", "downgrade", "07b8c9d0e1f2"], ["-m", "alembic", "upgrade", "head"]]
args = test_args
commands.append(["-m", "pytest", *(args or ["tests/integration"]), "-q", "--tb=short"])
for args in commands:
result = subprocess.run([str(python), *args], cwd=root / "backend", env=env)
if result.returncode:
return result.returncode
return 0
if __name__ == "__main__":
raise SystemExit(main())