48 lines
1.8 KiB
Python
48 lines
1.8 KiB
Python
"""labs 的统一入口:把 ``py-client`` 挂上 ``sys.path`` 后运行 labs/tests 下的全部单测。
|
||
|
||
为什么需要它:测试模块内部有 ``from tests.zt_harness import ...`` 这类导入,
|
||
所以 ``labs`` 必须作为顶层包被导入,同时 ``py-client`` 必须在 ``sys.path`` 上
|
||
(``config`` / ``libs`` / ``sdk`` / ``strategy`` 都在那里)。单独用
|
||
``python -m unittest discover`` 很难同时满足这两点,因此统一走这个脚本。
|
||
|
||
用法(在仓库任意位置执行):
|
||
py -3.14 -B labs/run_tests.py # 跑全部
|
||
py -3.14 -B labs/run_tests.py -v # 详细
|
||
py -3.14 -B labs/run_tests.py test_etf_signal # 只跑某个模块
|
||
"""
|
||
|
||
import sys
|
||
import unittest
|
||
from pathlib import Path
|
||
|
||
LABS = Path(__file__).resolve().parent
|
||
REPO = LABS.parent
|
||
PY_CLIENT = REPO / "py-client"
|
||
|
||
for path in (str(PY_CLIENT), str(REPO)):
|
||
if path not in sys.path:
|
||
sys.path.insert(0, path)
|
||
|
||
|
||
def build_suite(pattern: str, names: list[str]) -> unittest.TestSuite:
|
||
loader = unittest.TestLoader()
|
||
if names:
|
||
return loader.loadTestsFromNames(names)
|
||
start = LABS / "tests"
|
||
# top_level_dir 指向 labs:这样导入名是 tests.xxx,测试模块里的
|
||
# "from tests.zt_harness import ..." 才能解析。
|
||
return loader.discover(str(start), pattern=pattern, top_level_dir=str(LABS))
|
||
|
||
|
||
def main(argv: list[str]) -> int:
|
||
args = [a for a in argv if not a.startswith("-")]
|
||
verbosity = 2 if any(a in ("-v", "--verbose") for a in argv) else 1
|
||
names = [a if "." in a else f"tests.{a}" for a in args]
|
||
suite = build_suite("test_*.py", names)
|
||
result = unittest.TextTestRunner(verbosity=verbosity).run(suite)
|
||
return 0 if result.wasSuccessful() else 1
|
||
|
||
|
||
if __name__ == "__main__":
|
||
raise SystemExit(main(sys.argv[1:]))
|