mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-11-15 21:01:10 +08:00
134 lines
4.3 KiB
Python
134 lines
4.3 KiB
Python
"""
|
|
共享测试引导工具的回归用例。
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import builtins
|
|
import sys
|
|
import types
|
|
from pathlib import Path
|
|
|
|
from app.testing import bootstrap
|
|
|
|
|
|
def test_ensure_sites_stub_replaces_loaded_dynamic_resource(monkeypatch):
|
|
"""
|
|
隔离探针必须覆盖本机资源模块,保证 source-only CI 与开发机前提一致。
|
|
"""
|
|
real_module = types.ModuleType("app.application.site.sites")
|
|
real_module.SitesHelper = object
|
|
monkeypatch.setitem(sys.modules, "app.application.site.sites", real_module)
|
|
|
|
bootstrap.ensure_sites_stub()
|
|
|
|
installed = sys.modules["app.application.site.sites"]
|
|
assert installed is not real_module
|
|
assert installed.SitesHelper is bootstrap._SitesHelperStub
|
|
|
|
|
|
def test_prepare_backend_replaces_loaded_dynamic_resource(monkeypatch):
|
|
"""
|
|
普通测试引导必须隔离源码目录中已存在的站点原生制品。
|
|
"""
|
|
real_module = types.ModuleType("app.application.site.sites")
|
|
real_module.SitesHelper = object
|
|
monkeypatch.setitem(sys.modules, "app.application.site.sites", real_module)
|
|
|
|
bootstrap.prepare_backend()
|
|
|
|
installed = sys.modules["app.application.site.sites"]
|
|
assert installed is not real_module
|
|
assert installed.SitesHelper is bootstrap._SitesHelperStub
|
|
|
|
|
|
def test_isolate_config_cleanup_uses_loaded_db_module_without_late_import(monkeypatch):
|
|
"""
|
|
清理回调只读取已加载模块,避免解释器关停期触发二次导入。
|
|
"""
|
|
captured = {}
|
|
import_calls = []
|
|
|
|
def fake_import(name, *args, **kwargs):
|
|
"""
|
|
记录清理回调是否试图重新导入数据库模块。
|
|
"""
|
|
if name == "app.db":
|
|
import_calls.append(name)
|
|
return original_import(name, *args, **kwargs)
|
|
|
|
def fake_register(func):
|
|
"""
|
|
截获 atexit 回调,便于直接验证清理行为。
|
|
"""
|
|
captured["cleanup"] = func
|
|
|
|
monkeypatch.setattr(bootstrap, "_isolated_config_dir", None)
|
|
monkeypatch.delenv("CONFIG_DIR", raising=False)
|
|
monkeypatch.setattr(bootstrap.tempfile, "mkdtemp", lambda prefix: "/tmp/mp-test-config-demo")
|
|
monkeypatch.setattr(bootstrap.shutil, "rmtree", lambda *args, **kwargs: None)
|
|
monkeypatch.setattr(bootstrap.atexit, "register", fake_register)
|
|
|
|
original_import = builtins.__import__
|
|
monkeypatch.setattr(builtins, "__import__", fake_import)
|
|
|
|
bootstrap.isolate_config_dir()
|
|
captured["cleanup"]()
|
|
|
|
assert import_calls == []
|
|
|
|
|
|
def test_mark_plugin_generation_prefers_pathlib_item_path():
|
|
"""
|
|
pytest 新版 item.path 可独立驱动 v1/v2 marker 标记。
|
|
"""
|
|
|
|
class FakeItem:
|
|
"""
|
|
只暴露 pytest 7+ 的 path 属性,模拟新版收集对象。
|
|
"""
|
|
|
|
def __init__(self, value: str):
|
|
self.path = Path(value)
|
|
self.markers = []
|
|
|
|
def add_marker(self, marker):
|
|
"""
|
|
记录被添加的 marker。
|
|
"""
|
|
self.markers.append(marker)
|
|
|
|
pytest_module = types.SimpleNamespace(mark=types.SimpleNamespace(v1="v1", v2="v2"))
|
|
v2_item = FakeItem("/repo/tests/v2/test_demo.py")
|
|
v1_item = FakeItem("/repo/tests/v1/test_demo.py")
|
|
|
|
bootstrap.mark_plugin_generation([v2_item, v1_item], pytest_module)
|
|
|
|
assert v2_item.markers == ["v2"]
|
|
assert v1_item.markers == ["v1"]
|
|
|
|
|
|
def test_prepare_backend_wires_site_protocol_for_standalone_plugin_runners():
|
|
"""
|
|
不依赖后端 tests/conftest.py 的独立插件测试进程在调用 prepare_backend 后可直接解析站点域名协议。
|
|
"""
|
|
import subprocess
|
|
|
|
project_root = Path(__file__).resolve().parents[1]
|
|
code = (
|
|
"from app.testing.bootstrap import prepare_backend; "
|
|
"prepare_backend(); "
|
|
"from app.runtime.extensions.module.manager import ModuleManager; "
|
|
"assert ModuleManager.get_existing_instance() is None; "
|
|
"from app.sdk.string import StringUtils; "
|
|
"assert StringUtils.get_url_domain('https://u2.dmhy.org/torrents.php') == 'u2.dmhy.org'; "
|
|
"assert StringUtils.get_url_domain('https://tracker.example.com/rss') == 'example.com'"
|
|
)
|
|
result = subprocess.run(
|
|
[sys.executable, "-c", code],
|
|
cwd=project_root,
|
|
capture_output=True,
|
|
text=True,
|
|
check=False,
|
|
)
|
|
assert result.returncode == 0, result.stderr or result.stdout
|