测试模块初步完成

This commit is contained in:
qing committed 2026-07-28 09:39:37 +08:00
1 parent 4ad3fbfca8
commit d06546f6bf
13 files changed
+2162

No files matched your search

+188
View File
@@ -0,0 +1,188 @@
"""
micro_servers 黑盒测试 — 统一运行入口。
用法:
python3 test_runner.py # 运行全部测试
python3 test_runner.py --url http://127.0.0.1:8443 # 测试指定服务
python3 test_runner.py --list # 列出可用测试
python3 test_runner.py --service gateway # 按服务名运行
"""
import argparse
import importlib
import os
import sys
# 确保当前目录在 path 中
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from config import SERVICES, PORT_MAP, detect_service, get_url
from helpers import check_service
TEST_MODULES = {
"gateway": "test_gateway",
"captcha": "test_captcha",
"smtp": "test_smtp",
"dnfs": "test_dnfs",
"db": "test_db",
"ai_review": "test_ai_review",
"static": "test_static",
"waf": "test_waf",
}
def run_service_test(name: str, url: str) -> tuple:
"""运行单个服务的测试,返回 (passed, failed, skipped)。"""
module_name = TEST_MODULES.get(name)
if not module_name:
print(f"未知服务: {name}")
return 0, 0, 0
try:
mod = importlib.import_module(module_name)
except ImportError as e:
print(f"无法加载测试模块 {module_name}: {e}")
return 0, 0, 0
if not hasattr(mod, "run"):
print(f"模块 {module_name} 缺少 run(url) 函数")
return 0, 0, 0
svc = SERVICES[name]
print(f"\n{'='*60}")
print(f" {svc['description']} ({url})")
print(f"{'='*60}")
reachable, detail = check_service(url)
if not reachable:
print(f" [WARN] 服务不可达: {url}")
if detail:
print(f" 原因: {detail}")
print(f" 所有测试将被跳过。请先启动服务。\n")
return 0, 0, 0
passed, failed, skipped = mod.run(url)
return passed, failed, skipped
def run_all():
"""运行全部服务的测试。"""
total_passed = 0
total_failed = 0
total_skipped = 0
for name in SERVICES:
url = get_url(name)
p, f, s = run_service_test(name, url)
total_passed += p
total_failed += f
total_skipped += s
total = total_passed + total_failed + total_skipped
print(f"\n{'='*60}")
print(f" 全部测试完成: {total} total, "
f"{total_passed} passed, {total_failed} failed, {total_skipped} skipped")
print(f"{'='*60}")
return total_failed
def run_by_url(url: str):
"""以 URL 为入口,测试全部可代理服务,内部服务自动回退 localhost。
可代理服务 (通过 WAF→gateway 代理链): waf, gateway, static, dnfs
内部服务 (仅 localhost 直连): db, ai_review, captcha, smtp
"""
from urllib.parse import urlparse
hostname = urlparse(url).hostname or ""
is_remote = hostname not in ("127.0.0.1", "localhost", "::1")
if is_remote:
print(f" 入口: {url}")
print(f" 可代理服务 (waf/gateway/static/dnfs) 通过入口测试")
print(f" 内部服务 (db/ai_review/captcha/smtp) 回退到 localhost")
print()
# 可通过入口 URL 访问的服务
proxyable = {"waf", "gateway", "static", "dnfs"}
total_passed = 0
total_failed = 0
total_skipped = 0
for name in SERVICES:
if name in proxyable:
service_url = url
else:
service_url = get_url(name)
p, f, s = run_service_test(name, service_url)
total_passed += p
total_failed += f
total_skipped += s
total = total_passed + total_failed + total_skipped
print(f"\n{'='*60}")
print(f" 全部测试完成: {total} total, "
f"{total_passed} passed, {total_failed} failed, {total_skipped} skipped")
print(f"{'='*60}")
return total_failed
def run_by_name(name: str):
"""按服务名运行测试。"""
svc = SERVICES.get(name)
if not svc:
print(f"未知服务: {name}")
print(f"可用服务: {', '.join(SERVICES.keys())}")
return 1
url = get_url(name)
p, f, s = run_service_test(name, url)
return f
def list_tests():
"""列出所有可用测试。"""
print("可用的黑盒测试:\n")
for name, svc in SERVICES.items():
print(f" {name:12s} 端口 {svc['port']:<5d} {svc['description']}")
print()
def main():
parser = argparse.ArgumentParser(
description="micro_servers 黑盒用户模拟测试",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
示例:
%(prog)s # 全部服务 localhost 测试
%(prog)s --url https://qsont.me # 公网入口测试全部可代理服务
%(prog)s --url http://127.0.0.1:8443 # 本地入口测试全部
%(prog)s --service gateway # 仅测试指定服务
%(prog)s --list # 列出可用测试
""",
)
parser.add_argument("--url", help="入口 URL,通过它测试全部可代理服务(内部服务回退 localhost)")
parser.add_argument("--service", help="按服务名称运行测试")
parser.add_argument("--list", action="store_true", help="列出所有可用测试")
args = parser.parse_args()
if args.list:
list_tests()
return 0
if args.url:
return run_by_url(args.url)
if args.service:
return run_by_name(args.service)
# 默认:运行全部
return run_all()
if __name__ == "__main__":
sys.exit(main())