Introduce a comprehensive TTS/ASR module that: - Adds /v1/tts-asr/config, /status, /warmup, /tts, /asr endpoints with detailed JSON responses - Implements Apple‑Silicon detection, device selection (MPS/CUDA/CPU), and memory limiting logic - Supports selectable model size, quantization, and offline mode via environment variables - Adds robust audio validation and multi‑path resampling fallback - Provides new README sections for API usage, device detection, and performance benchmarking - Includes a full testing suite: unit tests, integration tests, macOS simulation and performance reports - Updates backend dependencies and CI scripts - Adds new front‑end views and components for Univer editor integration All changes are backward compatible; new features are exposed through environment variables and new API routes.
205 lines
5.8 KiB
Python
205 lines
5.8 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
"""
|
|
TTS/ASR测试运行器
|
|
便捷地运行各种测试组合
|
|
|
|
运行方式:
|
|
python backend/tests/run_tests.py --help
|
|
python backend/tests/run_tests.py unit
|
|
python backend/tests/run_tests.py integration
|
|
python backend/tests/run_tests.py simulate
|
|
python backend/tests/run_tests.py all
|
|
"""
|
|
|
|
import argparse
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
|
|
def run_command(cmd: list, cwd: str = None) -> int:
|
|
"""运行命令并返回退出码"""
|
|
print(f"\n执行: {' '.join(cmd)}")
|
|
print("-" * 70)
|
|
result = subprocess.run(cmd, cwd=cwd)
|
|
return result.returncode
|
|
|
|
|
|
def run_unit_tests(verbose: bool = False) -> int:
|
|
"""运行单元测试"""
|
|
print("\n" + "="*70)
|
|
print("运行单元测试")
|
|
print("="*70)
|
|
|
|
cmd = ['pytest', 'backend/tests/test_tts_asr_unit.py']
|
|
if verbose:
|
|
cmd.append('-v')
|
|
|
|
return run_command(cmd)
|
|
|
|
|
|
def run_integration_tests(test_type: str = None, url: str = None, key: str = None) -> int:
|
|
"""运行集成测试"""
|
|
print("\n" + "="*70)
|
|
print("运行集成测试")
|
|
print("="*70)
|
|
|
|
cmd = ['python', 'backend/tests/test_tts_asr_integration.py']
|
|
|
|
if test_type:
|
|
cmd.extend(['--test', test_type])
|
|
|
|
if url:
|
|
cmd.extend(['--url', url])
|
|
|
|
if key:
|
|
cmd.extend(['--key', key])
|
|
|
|
return run_command(cmd)
|
|
|
|
|
|
def run_simulation(test_type: str = None) -> int:
|
|
"""运行macOS模拟测试"""
|
|
print("\n" + "="*70)
|
|
print("运行macOS环境模拟测试")
|
|
print("="*70)
|
|
|
|
if test_type == 'full':
|
|
cmd = ['python', 'backend/tests/simulate_macos.py', '--full-simulation']
|
|
elif test_type:
|
|
cmd = ['python', 'backend/tests/simulate_macos.py', '--test', test_type]
|
|
else:
|
|
cmd = ['python', 'backend/tests/simulate_macos.py', '--full-simulation']
|
|
|
|
return run_command(cmd)
|
|
|
|
|
|
def run_all_tests(url: str = None, key: str = None) -> int:
|
|
"""运行所有测试"""
|
|
print("\n" + "="*70)
|
|
print("运行完整测试套件")
|
|
print("="*70)
|
|
|
|
results = []
|
|
|
|
# 1. 单元测试
|
|
print("\n[1/3] 单元测试")
|
|
results.append(("单元测试", run_unit_tests(verbose=True)))
|
|
|
|
# 2. macOS模拟测试
|
|
print("\n[2/3] macOS模拟测试")
|
|
results.append(("macOS模拟", run_simulation(test_type='full')))
|
|
|
|
# 3. 集成测试(如果服务可用)
|
|
print("\n[3/3] 集成测试")
|
|
print("注意: 集成测试需要后端服务运行中")
|
|
response = input("是否继续运行集成测试? [y/N]: ")
|
|
|
|
if response.lower() == 'y':
|
|
results.append(("集成测试", run_integration_tests(url=url, key=key)))
|
|
else:
|
|
print("跳过集成测试")
|
|
results.append(("集成测试", 0))
|
|
|
|
# 汇总结果
|
|
print("\n" + "="*70)
|
|
print("测试结果汇总")
|
|
print("="*70)
|
|
|
|
total_passed = 0
|
|
for name, code in results:
|
|
status = "✓ 通过" if code == 0 else "✗ 失败"
|
|
print(f"{name}: {status}")
|
|
if code == 0:
|
|
total_passed += 1
|
|
|
|
print("\n" + "-"*70)
|
|
print(f"总计: {total_passed}/{len(results)} 测试套件通过")
|
|
print("="*70)
|
|
|
|
return 0 if all(code == 0 for _, code in results) else 1
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(
|
|
description='TTS/ASR测试运行器',
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
epilog="""
|
|
示例:
|
|
# 运行单元测试
|
|
python backend/tests/run_tests.py unit
|
|
|
|
# 运行集成测试
|
|
python backend/tests/run_tests.py integration
|
|
|
|
# 运行macOS模拟测试
|
|
python backend/tests/run_tests.py simulate
|
|
|
|
# 运行所有测试
|
|
python backend/tests/run_tests.py all
|
|
|
|
# 运行特定集成测试
|
|
python backend/tests/run_tests.py integration --test config
|
|
|
|
# 运行特定模拟测试
|
|
python backend/tests/run_tests.py simulate --test device
|
|
"""
|
|
)
|
|
|
|
subparsers = parser.add_subparsers(dest='command', help='测试类型')
|
|
|
|
# 单元测试
|
|
unit_parser = subparsers.add_parser('unit', help='运行单元测试')
|
|
unit_parser.add_argument('-v', '--verbose', action='store_true', help='详细输出')
|
|
|
|
# 集成测试
|
|
integration_parser = subparsers.add_parser('integration', help='运行集成测试')
|
|
integration_parser.add_argument('--test', choices=[
|
|
'config', 'status', 'warmup', 'tts', 'asr', 'perf'
|
|
], help='运行特定测试')
|
|
integration_parser.add_argument('--url', default='http://localhost:8001', help='API URL')
|
|
integration_parser.add_argument('--key', default='your-secret-key-here', help='API密钥')
|
|
|
|
# macOS模拟测试
|
|
simulate_parser = subparsers.add_parser('simulate', help='运行macOS模拟测试')
|
|
simulate_parser.add_argument('--test', choices=[
|
|
'device', 'memory', 'model', 'audio', 'env', 'full'
|
|
], help='运行特定测试')
|
|
|
|
# 所有测试
|
|
all_parser = subparsers.add_parser('all', help='运行所有测试')
|
|
all_parser.add_argument('--url', default='http://localhost:8001', help='API URL')
|
|
all_parser.add_argument('--key', default='your-secret-key-here', help='API密钥')
|
|
|
|
args = parser.parse_args()
|
|
|
|
# 确保在项目根目录
|
|
project_root = Path(__file__).parent.parent.parent
|
|
os.chdir(project_root)
|
|
|
|
if args.command == 'unit':
|
|
return run_unit_tests(verbose=args.verbose)
|
|
|
|
elif args.command == 'integration':
|
|
return run_integration_tests(
|
|
test_type=args.test,
|
|
url=args.url,
|
|
key=args.key
|
|
)
|
|
|
|
elif args.command == 'simulate':
|
|
return run_simulation(test_type=args.test)
|
|
|
|
elif args.command == 'all':
|
|
return run_all_tests(url=args.url, key=args.key)
|
|
|
|
else:
|
|
parser.print_help()
|
|
return 0
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main())
|