Files
hunjing/tianmu/tests/conftest.py
2026-08-21 16:00:13 +08:00

85 lines
2.0 KiB
Python

"""
天目 pytest 配置。
提供服务启停夹具,方便运行集成测试。
"""
from __future__ import annotations
import json
import os
import subprocess
import time
import urllib.request
from pathlib import Path
import pytest
API_BASE = os.environ.get("TIANMU_API_BASE", "http://localhost:8101")
TIANMU_DIR = Path(__file__).resolve().parent.parent
def _wait_for_service(url: str, timeout: float = 15.0, interval: float = 0.5) -> bool:
"""轮询等待服务就绪。
Args:
url: 健康检查 URL。
timeout: 最长等待秒数。
interval: 轮询间隔秒数。
Returns:
True 表示服务就绪,False 表示超时。
"""
start = time.monotonic()
while time.monotonic() - start < timeout:
try:
req = urllib.request.Request(url, method="GET")
with urllib.request.urlopen(req, timeout=2) as resp:
if resp.status == 200:
return True
except (urllib.error.URLError, ConnectionError, OSError):
pass
time.sleep(interval)
return False
@pytest.fixture(scope="session")
def tianmu_server():
"""启动天目服务(仅一次,整个 session 共用)。
如果环境变量 TIANMU_API_BASE 已设置,跳过启动(连接外部服务)。
启动后轮询 /healthz,就绪后才继续运行测试。
"""
if "TIANMU_API_BASE" in os.environ:
yield
return
proc = subprocess.Popen(
["python3", "-m", "src.main"],
cwd=str(TIANMU_DIR),
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
ready = _wait_for_service(f"{API_BASE}/healthz")
if not ready:
proc.terminate()
proc.wait()
raise RuntimeError(
f"天目服务启动超时({API_BASE}/healthz 15s 内未就绪)"
)
yield
proc.terminate()
try:
proc.wait(timeout=5)
except subprocess.TimeoutExpired:
proc.kill()
proc.wait()
@pytest.fixture
def api_base() -> str:
return API_BASE