Files
xiaoxia-saas/tests/integration/test_full_pipeline.py
T
CI Bot e5e46bb02b
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 1m1s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m49s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m53s
AI Code Review / AI Code Review (pull_request) Successful in 2m9s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 2m12s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 2m19s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 4m40s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 3m54s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 46s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 54s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 7m56s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 7m5s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 4m46s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 14m59s
CI/CD Pipeline / CI Gate (pull_request) Successful in 7s
CI/CD Pipeline / Production Browser E2E (pull_request) Failing after 699h55m14s
CI/CD Pipeline / Deploy Production (pull_request) Failing after 699h55m16s
CI/CD Pipeline / Build Production Worker Image (pull_request) Failing after 699h55m18s
CI/CD Pipeline / Build Production API Image (pull_request) Failing after 699h55m20s
CI/CD Pipeline / PR Build Web Image (pull_request) Failing after 700h2m13s
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 700h2m16s
CI/CD Pipeline / ACR Image Cleanup (pull_request) Failing after 700h3m10s
CI/CD Pipeline / Staging API Integration Tests (pull_request) Failing after 700h3m12s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Failing after 700h3m16s
CI/CD Pipeline / Staging E2E Tests (pull_request) Failing after 700h3m12s
CI/CD Pipeline / Build Staging Web Image (pull_request) Failing after 700h3m16s
CI/CD Pipeline / Build Staging API Image (pull_request) Failing after 700h3m16s
CI/CD Pipeline / Canary Release to Production (pull_request) Failing after 700h28m56s
CI/CD Pipeline / Build Production Web Image (pull_request) Failing after 700h29m0s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Failing after 700h35m56s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Failing after 700h36m55s
style: auto-format with black + isort + prettier [skip ci-format-check]
2026-08-18 03:23:08 +00:00

190 lines
5.5 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.
"""全链路集成测试.
验证 PlanGeneratorService → UnifiedRenderService → 查重 的端到端流程。
"""
from __future__ import annotations
import shutil
import subprocess
import tempfile
from pathlib import Path
import pytest
from video_processing.unified_render_service import (
UnifiedRenderService,
)
from worker_app.tasks.generation import _build_plan_and_clips_from_task
pytestmark = pytest.mark.skipif(
not shutil.which("ffmpeg"),
reason="ffmpeg not available",
)
def _generate_test_video(path: Path, duration: float = 3.0) -> None:
"""生成一个测试视频。"""
cmd = [
"ffmpeg",
"-y",
"-f",
"lavfi",
"-i",
f"color=c=blue:s=640x360:d={duration}:r=25",
"-c:v",
"libx264",
"-pix_fmt",
"yuv420p",
str(path),
]
subprocess.run(cmd, check=True, capture_output=True, timeout=30)
def _generate_test_audio(path: Path, duration: float = 5.0) -> None:
"""生成一个测试音频文件。"""
cmd = [
"ffmpeg",
"-y",
"-f",
"lavfi",
"-i",
f"sine=frequency=440:duration={duration}",
"-c:a",
"aac",
"-b:a",
"128k",
str(path),
]
subprocess.run(cmd, check=True, capture_output=True, timeout=30)
class TestFullPipeline:
"""验证从虚拟 plan 构建到渲染输出的完整流程。"""
def test_one_take_pipeline(self):
"""ONE_TAKE 模式完整流程。"""
with tempfile.TemporaryDirectory() as tmpdir:
work_dir = Path(tmpdir)
# 生成测试素材
paths = []
for i in range(3):
p = work_dir / f"clip_{i}.mp4"
_generate_test_video(p, duration=2.0)
paths.append(p)
# 构建虚拟 plan
plan, clips, asset_map = _build_plan_and_clips_from_task("pipeline_test", paths, "one_take")
# 渲染
service = UnifiedRenderService(
plan=plan,
clips=clips,
asset_path_map=asset_map,
work_dir=work_dir,
output_width=640,
output_height=360,
)
result = service.render()
assert result.output_path.exists()
assert result.duration > 0
assert result.file_size > 0
assert result.width == 640
assert result.height == 360
def test_pipeline_with_audio_mux(self):
"""渲染 + 混音后处理。"""
with tempfile.TemporaryDirectory() as tmpdir:
work_dir = Path(tmpdir)
# 生成测试素材
video_path = work_dir / "clip_0.mp4"
_generate_test_video(video_path, duration=3.0)
# 构建虚拟 plan
plan, clips, asset_map = _build_plan_and_clips_from_task("audio_test", [video_path], "one_take")
# 渲染
service = UnifiedRenderService(
plan=plan,
clips=clips,
asset_path_map=asset_map,
work_dir=work_dir,
output_width=640,
output_height=360,
)
render_result = service.render()
# 混音 - 直接用 ffmpeg(_mux_audio_track 已被清理)
audio_path = work_dir / "voice.aac"
_generate_test_audio(audio_path, duration=5.0)
final_path = work_dir / "final.mp4"
mux_cmd = [
"ffmpeg",
"-y",
"-i",
str(render_result.output_path),
"-i",
str(audio_path),
"-c:v",
"copy",
"-c:a",
"aac",
"-shortest",
str(final_path),
]
subprocess.run(mux_cmd, check=True, capture_output=True, timeout=30)
assert final_path.exists()
assert final_path.stat().st_size > 0
def test_single_clip_pipeline(self):
"""单 clip 渲染(无转场)。"""
with tempfile.TemporaryDirectory() as tmpdir:
work_dir = Path(tmpdir)
video_path = work_dir / "single.mp4"
_generate_test_video(video_path, duration=5.0)
plan, clips, asset_map = _build_plan_and_clips_from_task("single_test", [video_path], "one_take")
service = UnifiedRenderService(
plan=plan,
clips=clips,
asset_path_map=asset_map,
work_dir=work_dir,
output_width=640,
output_height=360,
)
result = service.render()
assert result.output_path.exists()
assert result.duration > 0
def test_dedup_helper_integration(self):
"""验证 dedup_helpers.create_video_record_and_dedup 的导入和签名。"""
# 只验证函数存在且签名正确(不实际调用,需要数据库)
import inspect
from video_processing.dedup_helpers import create_video_record_and_dedup
sig = inspect.signature(create_video_record_and_dedup)
params = set(sig.parameters.keys())
expected = {
"generation_task_id",
"project_id",
"batch_id",
"file_url",
"file_size",
"duration",
"video_path",
"mode",
"session",
"width",
"height",
"fps",
}
assert expected.issubset(params), f"Missing params: {expected - params}"