258 lines
8.9 KiB
Python
258 lines
8.9 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
测试直接导入方式的视频拆分服务
|
||
验证类型安全和简洁性
|
||
"""
|
||
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
# 添加项目根目录到Python路径
|
||
project_root = Path(__file__).parent.parent
|
||
sys.path.insert(0, str(project_root))
|
||
|
||
def test_direct_import():
|
||
"""测试直接导入"""
|
||
print("🔍 测试直接导入方式")
|
||
print("=" * 50)
|
||
|
||
try:
|
||
# 直接导入,如果依赖不存在就立即失败
|
||
from python_core.services.video_splitter import VideoSplitterService, DetectionConfig, DetectorType
|
||
print("✅ 模块导入成功")
|
||
|
||
# 测试类型提示
|
||
service: VideoSplitterService = VideoSplitterService()
|
||
print("✅ 类型提示正常工作")
|
||
|
||
# 测试配置创建
|
||
config: DetectionConfig = DetectionConfig(
|
||
threshold=30.0,
|
||
detector_type=DetectorType.CONTENT
|
||
)
|
||
print("✅ 配置创建成功,类型安全")
|
||
|
||
return True
|
||
|
||
except ImportError as e:
|
||
print(f"❌ 导入失败(这是预期的,如果依赖不存在): {e}")
|
||
# 检查错误信息是否明确
|
||
if "scenedetect" in str(e).lower():
|
||
print("✅ 错误信息明确指出了缺失的依赖")
|
||
return True
|
||
else:
|
||
print("⚠️ 错误信息可能不够明确")
|
||
return False
|
||
except Exception as e:
|
||
print(f"❌ 意外错误: {e}")
|
||
return False
|
||
|
||
def test_type_safety():
|
||
"""测试类型安全"""
|
||
print("\n🔒 测试类型安全")
|
||
print("=" * 50)
|
||
|
||
try:
|
||
# 检查PySceneDetect
|
||
try:
|
||
import scenedetect
|
||
print(f"✅ PySceneDetect {scenedetect.__version__} 可用")
|
||
except ImportError:
|
||
print("⚠️ PySceneDetect不可用,跳过类型安全测试")
|
||
return True
|
||
|
||
from python_core.services.video_splitter.detectors import PySceneDetectDetector
|
||
from python_core.services.video_splitter.types import DetectionConfig, DetectorType
|
||
|
||
# 测试检测器创建
|
||
detector = PySceneDetectDetector()
|
||
print("✅ 检测器创建成功")
|
||
|
||
# 测试类型提示在IDE中的工作
|
||
# 这些应该有完整的类型提示
|
||
config = DetectionConfig(threshold=25.0)
|
||
print(f"✅ 配置类型: {type(config)}")
|
||
print(f" 阈值: {config.threshold}")
|
||
print(f" 检测器类型: {config.detector_type}")
|
||
print(f" 最小场景长度: {config.min_scene_length}")
|
||
|
||
# 测试枚举类型
|
||
content_type = DetectorType.CONTENT
|
||
threshold_type = DetectorType.THRESHOLD
|
||
print(f"✅ 枚举类型工作正常: {content_type.value}, {threshold_type.value}")
|
||
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"❌ 类型安全测试失败: {e}")
|
||
return False
|
||
|
||
def test_functionality():
|
||
"""测试功能"""
|
||
print("\n🎯 测试功能")
|
||
print("=" * 50)
|
||
|
||
try:
|
||
# 检查依赖
|
||
try:
|
||
import scenedetect
|
||
except ImportError:
|
||
print("⚠️ PySceneDetect不可用,跳过功能测试")
|
||
return True
|
||
|
||
from python_core.services.video_splitter import VideoSplitterService, DetectionConfig
|
||
|
||
# 查找测试视频
|
||
assets_dir = project_root / "assets"
|
||
video_files = list(assets_dir.rglob("*.mp4"))
|
||
|
||
if not video_files:
|
||
print("⚠️ 没有找到测试视频,跳过功能测试")
|
||
return True
|
||
|
||
test_video = str(video_files[0])
|
||
print(f"📹 测试视频: {test_video}")
|
||
|
||
# 创建服务
|
||
service = VideoSplitterService()
|
||
print("✅ 服务创建成功")
|
||
|
||
# 测试分析
|
||
config = DetectionConfig(threshold=30.0)
|
||
result = service.analyze_video(test_video, config)
|
||
|
||
if result.success:
|
||
print(f"✅ 视频分析成功:")
|
||
print(f" 总场景数: {result.total_scenes}")
|
||
print(f" 总时长: {result.total_duration:.2f}秒")
|
||
print(f" 分析时间: {result.analysis_time:.2f}秒")
|
||
|
||
# 验证场景数据类型
|
||
for i, scene in enumerate(result.scenes[:2]): # 只显示前2个
|
||
print(f" 场景 {scene.scene_number}: {scene.start_time:.2f}s - {scene.end_time:.2f}s")
|
||
# 验证类型
|
||
assert isinstance(scene.scene_number, int)
|
||
assert isinstance(scene.start_time, float)
|
||
assert isinstance(scene.end_time, float)
|
||
|
||
print("✅ 场景数据类型验证通过")
|
||
else:
|
||
print(f"❌ 视频分析失败: {result.error}")
|
||
return False
|
||
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"❌ 功能测试失败: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return False
|
||
|
||
def test_code_simplicity():
|
||
"""测试代码简洁性"""
|
||
print("\n📝 测试代码简洁性")
|
||
print("=" * 50)
|
||
|
||
try:
|
||
# 检查文件大小和复杂度
|
||
module_dir = project_root / "python_core" / "services" / "video_splitter"
|
||
|
||
files_to_check = ["detectors.py", "service.py", "cli.py"]
|
||
|
||
for file_name in files_to_check:
|
||
file_path = module_dir / file_name
|
||
if file_path.exists():
|
||
content = file_path.read_text()
|
||
lines = content.splitlines()
|
||
|
||
# 统计代码行数(排除空行和注释)
|
||
code_lines = [line for line in lines if line.strip() and not line.strip().startswith('#')]
|
||
|
||
print(f"✅ {file_name}:")
|
||
print(f" 总行数: {len(lines)}")
|
||
print(f" 代码行数: {len(code_lines)}")
|
||
|
||
# 检查是否有复杂的条件逻辑
|
||
complex_patterns = ['if UTILS_AVAILABLE', 'try:', 'except ImportError', 'AVAILABLE = True']
|
||
complex_count = sum(1 for line in lines if any(pattern in line for pattern in complex_patterns))
|
||
|
||
if complex_count == 0:
|
||
print(f" ✅ 没有复杂的降级逻辑")
|
||
else:
|
||
print(f" ⚠️ 仍有 {complex_count} 行复杂逻辑")
|
||
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"❌ 代码简洁性测试失败: {e}")
|
||
return False
|
||
|
||
def main():
|
||
"""主函数"""
|
||
print("🚀 测试直接导入方式的视频拆分服务")
|
||
print("验证类型安全和代码简洁性")
|
||
|
||
try:
|
||
# 运行所有测试
|
||
tests = [
|
||
test_direct_import,
|
||
test_type_safety,
|
||
test_functionality,
|
||
test_code_simplicity
|
||
]
|
||
|
||
results = []
|
||
for test in tests:
|
||
try:
|
||
result = test()
|
||
results.append(result)
|
||
except Exception as e:
|
||
print(f"❌ 测试 {test.__name__} 异常: {e}")
|
||
results.append(False)
|
||
|
||
# 总结
|
||
print("\n" + "=" * 60)
|
||
print("📊 直接导入测试总结")
|
||
print("=" * 60)
|
||
|
||
passed = sum(results)
|
||
total = len(results)
|
||
|
||
print(f"通过测试: {passed}/{total}")
|
||
|
||
if passed == total:
|
||
print("🎉 所有直接导入测试通过!")
|
||
print("\n✅ 直接导入的优势:")
|
||
print(" 1. 类型安全 - 完整的类型提示和IDE支持")
|
||
print(" 2. 代码简洁 - 移除了复杂的依赖检查逻辑")
|
||
print(" 3. 明确失败 - 依赖问题立即暴露")
|
||
print(" 4. 易于理解 - 代码逻辑清晰直观")
|
||
print(" 5. 性能更好 - 没有运行时的条件判断")
|
||
|
||
print("\n🔧 代码质量改进:")
|
||
print(" 1. 移除了 try/except ImportError 逻辑")
|
||
print(" 2. 移除了 AVAILABLE 标志变量")
|
||
print(" 3. 移除了条件导入和字典访问")
|
||
print(" 4. 保持了完整的类型信息")
|
||
print(" 5. IDE 可以提供完整的自动补全")
|
||
|
||
print("\n📝 使用方式:")
|
||
print(" # 直接导入,类型安全")
|
||
print(" from python_core.services.video_splitter import VideoSplitterService")
|
||
print(" service = VideoSplitterService() # 有完整类型提示")
|
||
|
||
return 0
|
||
else:
|
||
print("⚠️ 部分直接导入测试失败")
|
||
return 1
|
||
|
||
except Exception as e:
|
||
print(f"❌ 测试过程中出错: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return 1
|
||
|
||
if __name__ == "__main__":
|
||
exit_code = main()
|
||
sys.exit(exit_code)
|