162 lines
4.3 KiB
Python
162 lines
4.3 KiB
Python
"""
|
|
Pytest fixtures for UI testing
|
|
"""
|
|
|
|
import os
|
|
import subprocess
|
|
import time
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
from playwright.sync_api import Browser, Page
|
|
|
|
|
|
# 测试服务器配置
|
|
TEST_SERVER_HOST = os.getenv("TEST_SERVER_HOST", "localhost")
|
|
TEST_SERVER_PORT = int(os.getenv("TEST_SERVER_PORT", "8000"))
|
|
BASE_URL = f"http://{TEST_SERVER_HOST}:{TEST_SERVER_PORT}"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def test_server():
|
|
"""
|
|
启动测试服务器(如果未运行)
|
|
|
|
如果服务器已经在运行,直接返回 URL。
|
|
否则,启动一个测试服务器进程。
|
|
"""
|
|
# 检查服务器是否已经在运行
|
|
try:
|
|
import requests
|
|
response = requests.get(BASE_URL, timeout=2)
|
|
if response.status_code < 500:
|
|
print(f"✓ 服务器已在运行: {BASE_URL}")
|
|
yield BASE_URL
|
|
return
|
|
except:
|
|
pass
|
|
|
|
# 启动服务器
|
|
print(f"启动测试服务器: {BASE_URL}")
|
|
project_root = Path(__file__).parent.parent
|
|
|
|
process = subprocess.Popen(
|
|
[
|
|
"uvicorn",
|
|
"app.main:app",
|
|
"--host", TEST_SERVER_HOST,
|
|
"--port", str(TEST_SERVER_PORT),
|
|
],
|
|
cwd=project_root,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE,
|
|
)
|
|
|
|
# 等待服务器启动
|
|
max_retries = 30
|
|
for i in range(max_retries):
|
|
try:
|
|
import requests
|
|
response = requests.get(BASE_URL, timeout=2)
|
|
if response.status_code < 500:
|
|
print(f"✓ 服务器启动成功 (尝试 {i+1}/{max_retries})")
|
|
break
|
|
except:
|
|
pass
|
|
time.sleep(1)
|
|
else:
|
|
process.kill()
|
|
raise RuntimeError(f"无法启动测试服务器: {BASE_URL}")
|
|
|
|
yield BASE_URL
|
|
|
|
# 清理
|
|
print("停止测试服务器")
|
|
process.terminate()
|
|
try:
|
|
process.wait(timeout=5)
|
|
except subprocess.TimeoutExpired:
|
|
process.kill()
|
|
|
|
|
|
@pytest.fixture
|
|
def browser_context_args(browser_context_args):
|
|
"""配置浏览器上下文"""
|
|
return {
|
|
**browser_context_args,
|
|
"viewport": {"width": 1920, "height": 1080},
|
|
"locale": "zh-CN",
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def page(page: Page, test_server):
|
|
"""
|
|
配置页面并导航到首页
|
|
|
|
自动导航到测试服务器的首页,并等待页面加载完成。
|
|
"""
|
|
page.goto(test_server)
|
|
page.wait_for_load_state("networkidle")
|
|
|
|
# 设置默认超时
|
|
page.set_default_timeout(10000) # 10 秒
|
|
|
|
yield page
|
|
|
|
# 测试失败时截图
|
|
if page.context.browser.is_connected():
|
|
try:
|
|
screenshots_dir = Path(__file__).parent / "screenshots"
|
|
screenshots_dir.mkdir(exist_ok=True)
|
|
|
|
test_name = os.environ.get("PYTEST_CURRENT_TEST", "unknown").split(":")[-1].split(" ")[0]
|
|
screenshot_path = screenshots_dir / f"{test_name}.png"
|
|
|
|
page.screenshot(path=str(screenshot_path))
|
|
print(f"截图保存至: {screenshot_path}")
|
|
except Exception as e:
|
|
print(f"截图失败: {e}")
|
|
|
|
|
|
@pytest.fixture
|
|
def clean_rules(page: Page):
|
|
"""
|
|
清除所有规则的 fixture
|
|
|
|
在测试前清除所有现有的正则规则,确保测试从干净状态开始。
|
|
"""
|
|
# 清除所有规则
|
|
while page.locator(".rule-row").count() > 0:
|
|
try:
|
|
remove_btn = page.locator(".rule-row button[title='删除此规则']").first
|
|
remove_btn.click()
|
|
page.wait_for_timeout(50)
|
|
except:
|
|
break # 如果没有更多规则可删除
|
|
|
|
yield
|
|
|
|
# 测试后不清理,让下一个测试自己清理
|
|
# 这样可以在浏览器中查看测试结果
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_rules():
|
|
"""提供示例规则数据"""
|
|
return [
|
|
{"pattern": r"/old/path/", "replacement": r"/new/path/"},
|
|
{"pattern": r"C:\\Music", "replacement": r"D:\\Audio"},
|
|
{"pattern": r"\\\\nas\\share", "replacement": r"Z:"},
|
|
]
|
|
|
|
|
|
@pytest.fixture
|
|
def nas_conversion_rules():
|
|
"""提供 NAS 路径转换规则"""
|
|
return [
|
|
{"pattern": r"\\\\koha9-nas\\koha9-nas\\Music", "replacement": r"N:\\Music"},
|
|
{"pattern": r"/music/cache/", "replacement": r"/data/music/"},
|
|
{"pattern": r"\\", "replacement": r"/"},
|
|
]
|