From df732731d97775bd49a8508b147f9af2e9d78b90 Mon Sep 17 00:00:00 2001 From: InfinityPacer <160988576+InfinityPacer@users.noreply.github.com> Date: Mon, 1 Jun 2026 15:41:14 +0800 Subject: [PATCH] test: move config+db isolation to conftest, unify on pytest (#5868) --- .gitignore | 3 +++ tests/__init__.py | 21 +----------------- tests/conftest.py | 16 ++++++++++++++ tests/run.py | 54 +++++++++++------------------------------------ 4 files changed, 32 insertions(+), 62 deletions(-) create mode 100644 tests/conftest.py diff --git a/.gitignore b/.gitignore index a785b833..6619831f 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,6 @@ pylint-report.json .claude/ !.claude/*.json .claude/settings.local.json + +# Superpowers 设计/计划文档(本地协作产物,不纳入仓库) +docs/superpowers/ diff --git a/tests/__init__.py b/tests/__init__.py index 3380c4e4..747b5f60 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,20 +1 @@ -"""MoviePilot 后端测试包。 - -在导入任何用例之前隔离 CONFIG_DIR。测试普遍直接 ``import app.*``,而 app 在导入链路中 -按 ``settings.CONFIG_PATH`` 连接 ``user.db``:本地非容器布局下默认落到 -``MoviePilot/config/user.db``(线上真实库),``import app.chain.*`` 等在导入时即会建立/连接。 -本文件在 ``unittest discover``(会先导入 tests 包)与 ``pytest``(导入 tests.* 用例前先导入本包) -两种入口下都最先执行,故在此把 CONFIG_DIR 指向进程私有临时目录,避免测试连到或写入真实库与配置。 -已显式设置 CONFIG_DIR 时(如 CI 指定隔离目录)尊重之、不覆盖。 -""" -import atexit -import os -import shutil -import tempfile - -# 必须早于首个 import app.*:app.db 在导入时即按 CONFIG_PATH 建立/连接 user.db -if not os.environ.get("CONFIG_DIR"): - _isolated_config_dir = tempfile.mkdtemp(prefix="mp-test-config-") - os.environ["CONFIG_DIR"] = _isolated_config_dir - # 进程退出时清理临时库与目录,避免 /tmp 堆积 - atexit.register(shutil.rmtree, _isolated_config_dir, ignore_errors=True) +"""MoviePilot 后端测试包。隔离逻辑见 tests/conftest.py。""" diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 00000000..d7352d88 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,16 @@ +"""pytest 全局引导:在 import 任何测试模块前把 CONFIG_DIR 指向临时目录并建表,隔离真实库。""" +import atexit +import os +import shutil +import tempfile + +# 必须早于首个 import app.*:app.db 在导入时即按 CONFIG_PATH 连接 user.db +if not os.environ.get("CONFIG_DIR"): + _isolated_config_dir = tempfile.mkdtemp(prefix="mp-test-config-") + os.environ["CONFIG_DIR"] = _isolated_config_dir + atexit.register(shutil.rmtree, _isolated_config_dir, ignore_errors=True) + +# 必须在 CONFIG_DIR 设好之后再 import;空库会让运行期查表报 no such table,故建表 +from app.db.init import init_db # noqa: E402 + +init_db() diff --git a/tests/run.py b/tests/run.py index 4176c961..91cd4b30 100644 --- a/tests/run.py +++ b/tests/run.py @@ -1,45 +1,15 @@ -import unittest +"""核心回归集入口:以 pytest 跑一组核心测试文件,命令行参数透传给 pytest。""" +import sys -from tests.test_bluray import BluRayTest -from tests.test_mediascrape import ( - TestMediaScrapingPaths, - TestMediaScrapingNFO, - TestMediaScrapingImages, - TestMediaScrapingTVDirectory, - TestMediaScrapeEvents -) -from tests.test_metainfo import MetaInfoTest -from tests.test_object import ObjectUtilsTest -from tests.test_subscribe_chain import SubscribeChainTest +import pytest +CORE = [ + "tests/test_metainfo.py", + "tests/test_object.py", + "tests/test_bluray.py", + "tests/test_mediascrape.py", + "tests/test_subscribe_chain.py", +] -if __name__ == '__main__': - suite = unittest.TestSuite() - - # 测试名称识别 - suite.addTest(MetaInfoTest('test_metainfo')) - suite.addTest(MetaInfoTest('test_emby_format_ids')) - suite.addTest(ObjectUtilsTest('test_check_method')) - - # 测试自定义识别词功能 - suite.addTest(MetaInfoTest('test_metainfopath_with_custom_words')) - suite.addTest(MetaInfoTest('test_metainfopath_without_custom_words')) - suite.addTest(MetaInfoTest('test_metainfopath_with_empty_custom_words')) - suite.addTest(MetaInfoTest('test_custom_words_apply_words_recording')) - - # 测试蓝光目录识别 - suite.addTest(BluRayTest()) - - # 测试媒体刮削 - suite.addTest(unittest.TestLoader().loadTestsFromTestCase(TestMediaScrapingPaths)) - suite.addTest(unittest.TestLoader().loadTestsFromTestCase(TestMediaScrapingNFO)) - suite.addTest(unittest.TestLoader().loadTestsFromTestCase(TestMediaScrapingImages)) - suite.addTest(unittest.TestLoader().loadTestsFromTestCase(TestMediaScrapingTVDirectory)) - suite.addTest(unittest.TestLoader().loadTestsFromTestCase(TestMediaScrapeEvents)) - - # 测试订阅洗版匹配 - suite.addTest(SubscribeChainTest('test_is_episode_range_covered_matches_pending_episodes')) - - # 运行测试 - runner = unittest.TextTestRunner() - runner.run(suite) +if __name__ == "__main__": + sys.exit(pytest.main(CORE + sys.argv[1:]))