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
157 lines
5.4 KiB
Python
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()
|