Files
xiaoxia-saas/scripts/smoke_test.py
T
灵应 a620085dbb
Deploy / Staging E2E Tests (push) Has been skipped
Deploy / Build Production Runtime Images (push) Has been skipped
Deploy / Deploy Production (push) Has been skipped
Deploy / Production Browser E2E (push) Has been skipped
Deploy / Deploy Staging (push) Failing after 137h51m0s
CI/CD Pipeline / Frontend Lint (push) Failing after 137h51m10s
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 137h51m10s
style: 补全alembic和scripts目录isort排序
2026-07-03 19:03:18 +08:00

157 lines
5.4 KiB
Python

#!/usr/bin/env python3
"""
冒烟测试脚本 - 部署后自动验证核心端点可用性
用法: python3 smoke_test.py <API_BASE_URL> [--email EMAIL] [--password PASSWORD] [--json]
示例: python3 smoke_test.py https://saas-api.xiaoxiajianji.com --email test@example.com --password test123 --json
"""
import argparse
import json
import logging
import ssl
import sys
import time
import urllib.error
import urllib.request
logger = logging.getLogger(__name__)
CORE_ENDPOINTS = [
{
"name": "upload/direct/prepare",
"method": "POST",
"path": "/api/v1/upload/direct/prepare",
"body": {"project_id": "smoke-test", "file_name": "test.mp4", "file_size": 1024, "content_type": "video/mp4"},
"expect": [200, 401, 422],
},
{
"name": "upload/chunk/init",
"method": "POST",
"path": "/api/v1/upload/chunk/init",
"body": {"project_id": "smoke-test", "file_name": "test.mp4", "file_size": 1024000, "total_chunks": 2},
"expect": [200, 401, 422],
},
{"name": "dashboard/overview", "method": "GET", "path": "/api/v1/dashboard/overview", "expect": [200, 401]},
{"name": "assets", "method": "GET", "path": "/api/v1/assets?library_id=smoke-test", "expect": [200, 401]},
{
"name": "generation/tasks",
"method": "POST",
"path": "/api/v1/generation/tasks",
"body": {},
"expect": [200, 401, 422],
},
]
def make_request(base_url, endpoint, token=None):
url = f"{base_url}{endpoint['path']}"
headers = {"Content-Type": "application/json"}
if token:
headers["Authorization"] = f"Bearer {token}"
data = json.dumps(endpoint.get("body", {})).encode() if endpoint.get("body") is not None else None
req = urllib.request.Request(url, data=data, headers=headers, method=endpoint["method"])
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
try:
start = time.time()
resp = urllib.request.urlopen(req, timeout=15, context=ctx)
elapsed = round((time.time() - start) * 1000)
body = resp.read().decode()
return {"status": resp.status, "elapsed_ms": elapsed, "body": body[:200], "error": None}
except urllib.error.HTTPError as e:
elapsed = round((time.time() - start) * 1000)
body = ""
try:
body = e.read().decode()[:200]
except:
logger.warning(f"Operation failed in scripts/smoke_test.py: {e}", exc_info=True)
return {"status": e.code, "elapsed_ms": elapsed, "body": body, "error": None}
except Exception as e:
return {"status": 0, "elapsed_ms": 0, "body": "", "error": str(e)}
def login(base_url, email, password):
url = f"{base_url}/api/v1/auth/login"
data = json.dumps({"email": email, "password": password}).encode()
req = urllib.request.Request(url, data=data, headers={"Content-Type": "application/json"}, method="POST")
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
try:
resp = urllib.request.urlopen(req, timeout=10, context=ctx)
body = json.loads(resp.read().decode())
return body.get("token") or body.get("data", {}).get("token") or body.get("access_token")
except:
return None
def run_smoke_test(base_url, email=None, password=None, output_json=False):
base_url = base_url.rstrip("/")
token = None
if email and password:
token = login(base_url, email, password)
if not output_json:
print(f"{'✅ 登录成功' if token else '⚠️ 登录失败,将以未认证模式测试'}")
results = []
all_passed = True
for ep in CORE_ENDPOINTS:
result = make_request(base_url, ep, token)
passed = result["status"] in ep["expect"] and result["error"] is None
is_5xx = 500 <= result["status"] < 600
if is_5xx:
passed = False
all_passed = False
results.append(
{
"name": ep["name"],
"path": ep["path"],
"status": result["status"],
"elapsed_ms": result["elapsed_ms"],
"passed": passed,
"error": result["error"],
"is_5xx": is_5xx,
}
)
if not output_json:
icon = "✅" if passed else "❌"
print(f" {icon} {ep['name']}: {result['status']} ({result['elapsed_ms']}ms)")
if output_json:
print(json.dumps({"success": all_passed, "results": results, "base_url": base_url}, indent=2))
return 0 if all_passed else 1
def main():
parser = argparse.ArgumentParser(description="冒烟测试 - 部署后核心端点验证")
parser.add_argument("base_url", help="API 基础地址,如 https://saas-api.xiaoxiajianji.com")
parser.add_argument("--email", help="登录邮箱")
parser.add_argument("--password", help="登录密码")
parser.add_argument("--json", action="store_true", help="JSON 格式输出")
args = parser.parse_args()
if not args.json:
print(f"\n🔍 冒烟测试: {args.base_url}")
print("-" * 50)
exit_code = run_smoke_test(args.base_url, args.email, args.password, args.json)
if not args.json:
print("-" * 50)
print(f"{'✅ 全部通过' if exit_code == 0 else '❌ 存在失败端点'}\n")
sys.exit(exit_code)
if __name__ == "__main__":
main()