Files
vrsub/tests/test_seed.py
T
cat-shark 4746e0363f feat: VRSub 单体应用(WOV 单机版)初始提交
为视频生成 VR 双眼字幕的单体实现:FastAPI 后端、调度器与全部节点
(提音/转写/翻译/ASS/抽帧/OCR/LLM 过滤)在单进程内运行。

- 节点协议(wov_sdk 数据模型)与分布式版保持一致,预留回退桥梁
- 工作流即数据:DAG 存于 workflows/*.json,模型/链路改动只改数据
- 调度器:拓扑顺序执行、断点续跑(产物重建)、任务暂停/继续
- 抽帧按帧间隔(select 按帧号精确取帧),VLM OCR 与 LLM 过滤使用
  自适应线程池弹性并发,并打印数据处理速度进度日志
- 100% 行覆盖率(pytest --cov-fail-under=100)
2026-08-16 23:58:25 +08:00

109 lines
4.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""种子数据测试。
验证从 workflows/*.json 数据文件加载默认工作流、幂等性,以及
开启种子与调度器后的应用生命周期。工作流定义来自数据文件而非代码。
"""
from pathlib import Path
from fastapi.testclient import TestClient
from wov_app.db import Database
from wov_app.main import app
from wov_app.seed import seed_default_workflows
# 单体根目录:tests/ 的上一级。
WORKSPACE = Path(__file__).resolve().parent.parent
def test_seed_default_workflows_idempotent(tmp_path) -> None:
"""验证从数据文件加载 demo/zh-direct 两个工作流且重复调用幂等。"""
db = Database(tmp_path / "wov.db")
created = seed_default_workflows(db)
assert created == 3
assert db.get_workflow("demo") is not None
assert db.get_workflow("zh-direct") is not None
# demoasr 显式声明 model_path 与长音频参数,模型选择完全数据化。
demo = db.get_latest_workflow_version("demo")["definition"]
assert demo["name"] == "视频字幕生成"
demo_asr = next(node for node in demo["nodes"] if node["id"] == "asr")
assert demo_asr["params"]["model_path"] == "faster-whisper-large-v3"
assert demo_asr["params"]["condition_on_previous_text"] is False
# zh-direct:使用中文直出模型并开启翻译任务。
zh = db.get_latest_workflow_version("zh-direct")["definition"]
assert zh["name"] == "中文直出字幕"
zh_asr = next(node for node in zh["nodes"] if node["id"] == "asr")
assert zh_asr["params"]["model_path"] == "whisper-large-v2-translate-zh-v0.2-st-ct2"
assert zh_asr["params"]["task"] == "translate"
# 再次调用不重复创建。
assert seed_default_workflows(db) == 0
assert len(db.list_workflow_versions("demo")) == 1
def test_seed_custom_dir_and_empty(tmp_path) -> None:
"""验证自定义数据目录的加载与空目录返回 0。"""
db = Database(tmp_path / "wov.db")
custom = tmp_path / "workflows"
custom.mkdir()
(custom / "a.json").write_text(
"""
{
"id": "flow-a",
"name": "Flow A",
"description": "custom",
"version": 1,
"definition": {
"name": "Flow A",
"version": 1,
"nodes": [{"id": "step", "node_type": "echo"}],
"edges": [],
"entry_inputs": {},
"final_outputs": {}
}
}
""",
encoding="utf-8",
)
assert seed_default_workflows(db, custom) == 1
assert db.get_workflow("flow-a") is not None
# 空目录返回 0。
empty = tmp_path / "empty"
empty.mkdir()
assert seed_default_workflows(db, empty) == 0
# 已存在的工作流被跳过。
assert seed_default_workflows(db, custom) == 0
def test_lifespan_with_seed_and_scheduler(monkeypatch) -> None:
"""验证启用自动种子与调度器后应用正常启动,demo 与中文直出应用均可见。"""
monkeypatch.setenv("WOV_AUTO_SEED", "1")
monkeypatch.setenv("WOV_SCHEDULER_ENABLED", "1")
with TestClient(app) as client:
apps = client.get("/api/apps")
assert apps.status_code == 200
assert any(item["id"] == "demo" for item in apps.json())
assert any(item["id"] == "zh-direct" for item in apps.json())
def test_seed_workflows_have_chunk_seconds(tmp_path) -> None:
"""验证内置工作流的 asr 节点均显式声明分块参数。"""
db = Database(tmp_path / "wov.db")
seed_default_workflows(db)
for workflow_id in ("demo", "zh-direct"):
definition = db.get_latest_workflow_version(workflow_id)["definition"]
asr = next(node for node in definition["nodes"] if node["id"] == "asr")
assert asr["params"]["chunk_seconds"] == 60
def test_seed_workflows_vad_filter_off(tmp_path) -> None:
"""验证内置工作流 asr 显式开启 VAD。"""
db = Database(tmp_path / "wov.db")
seed_default_workflows(db)
for workflow_id in ("demo", "zh-direct"):
definition = db.get_latest_workflow_version(workflow_id)["definition"]
asr = next(node for node in definition["nodes"] if node["id"] == "asr")
assert asr["params"]["vad_filter"] is True