SenseVoice Small自动化测试:持续集成方案
1. 引言
1.1 业务场景描述
随着语音识别技术在智能交互、情感分析和内容理解等领域的广泛应用,构建稳定可靠的语音处理系统成为关键需求。SenseVoice Small 是基于 FunAudioLLM/SenseVoice 模型进行二次开发的轻量级语音识别工具,由开发者“科哥”定制化实现 WebUI 界面,支持多语言语音转文字,并具备情感事件标签识别能力。
在实际部署过程中,频繁的功能迭代与模型优化带来了回归风险。为保障每次代码变更后系统的功能一致性与稳定性,亟需建立一套自动化测试机制,并将其嵌入持续集成(CI)流程中。
1.2 痛点分析
当前项目面临以下挑战:
- 手动测试效率低,难以覆盖所有使用路径
- WebUI 功能更新后缺乏快速验证手段
- 多语言、多格式音频输入组合复杂,人工验证成本高
- 缺乏对情感/事件标签输出一致性的校验机制
1.3 方案预告
本文将介绍如何为SenseVoice Small WebUI构建完整的自动化测试体系,并通过 GitHub Actions 实现持续集成。我们将采用 Playwright 进行端到端 UI 测试,结合 Python 脚本完成结果断言,最终形成“提交即测试”的工程闭环。
2. 技术方案选型
2.1 自动化测试框架对比
| 工具 | 优势 | 劣势 | 适用性 |
|---|---|---|---|
| Selenium | 成熟稳定,社区广泛 | 需要浏览器驱动管理,速度慢 | ✅ 基础可用 |
| Puppeteer | Node.js 生态,性能好 | 仅限 Chrome/Chromium | ⚠️ 可用但非首选 |
| Playwright | 支持多浏览器、自动等待、截图录屏 | 学习曲线略陡 | ✅✅✅ 推荐选择 |
核心结论:Playwright 提供跨浏览器支持、原生等待机制和强大的网络拦截能力,非常适合 WebUI 自动化测试。
2.2 CI 平台选择
| 平台 | 易用性 | 成本 | 与 GitHub 集成度 | 是否推荐 |
|---|---|---|---|---|
| GitHub Actions | 高 | 免费(公开仓库) | 极佳 | ✅✅✅ |
| GitLab CI | 中 | 免费 | 一般 | ⚠️ |
| Jenkins | 低 | 自建成本高 | 差 | ❌ |
最终选择GitHub Actions作为 CI 执行引擎,无缝对接代码仓库,降低运维负担。
2.3 测试策略设计
我们采用分层测试策略:
- 单元测试:针对
run.sh启动脚本、配置加载逻辑等进行函数级测试 - 接口测试:调用 Gradio API 直接发送 POST 请求获取识别结果
- E2E 测试:模拟用户操作完整流程(上传 → 识别 → 校验)
本文重点聚焦于E2E 测试 + CI 集成。
3. 自动化测试实现步骤
3.1 环境准备
确保本地或 CI 环境满足以下条件:
# 安装依赖 pip install playwright pytest playwright install chromium # 启动应用服务 /bin/bash /root/run.sh > app.log 2>&1 &等待服务启动完成(可通过轮询http://localhost:7860判断是否就绪)。
3.2 编写 Playwright 测试脚本
# test_sensevoice.py from playwright.sync_api import sync_playwright, expect import time import os def test_sensevoice_end_to_end(): with sync_playwright() as p: # 启动浏览器 browser = p.chromium.launch(headless=True) page = browser.new_page() # 访问 WebUI page.goto("http://localhost:7860") expect(page.get_by_text("SenseVoice WebUI")).to_be_visible() expect(page.get_by_text("webUI二次开发 by 科哥")).to_be_visible() # 上传音频文件 audio_file_path = "tests/samples/zh.mp3" file_chooser = page.wait_for_event("filechooser") page.locator("input[type='file']").set_input_files(audio_file_path) # 选择语言为中文 page.select_option("select[id='language']", value="zh") # 点击开始识别 page.click("text=🚀 开始识别") # 等待识别结果出现 result_box = page.locator("textarea[id='result']") expect(result_box).to_have_text(re.compile(r".+😊|.+$"), timeout=30000) # 获取识别文本 text = result_box.input_value() print(f"识别结果: {text}") # 断言关键内容(以 zh.mp3 为例) assert "欢迎收听本期节目" in text assert "😊" in text or "HAPPY" in text # 截图留档 page.screenshot(path="results/test_success.png") browser.close()3.3 创建测试样本集
在tests/samples/目录下准备标准测试音频:
| 文件名 | 内容说明 | 预期输出关键词 |
|---|---|---|
| zh.mp3 | 中文对话 | “欢迎收听”,“😊” |
| en.mp3 | 英文朗读 | “The tribal chieftain” |
| emo_1.wav | 情感示例 | 包含 😡 或 😔 |
| rich_1.wav | 综合事件 | 🎼、👏、😊 等标签 |
每个样本应有明确的预期输出基准,便于自动化断言。
3.4 添加结果校验逻辑
扩展脚本以支持结构化解析:
def parse_result(text): """解析识别结果中的事件、文本、情感""" events = [] emotion = "NEUTRAL" content = text.strip() event_icons = {"🎼": "BGM", "👏": "Applause", "😀": "Laughter", "😭": "Cry"} emotion_icons = {"😊": "HAPPY", "😡": "ANGRY", "😔": "SAD"} for icon, label in event_icons.items(): if text.startswith(icon): events.append(label) content = content.lstrip(icon).strip() for icon, label in emotion_icons.items(): if text.endswith(icon): emotion = label content = content.rstrip(icon).strip() return {"events": events, "text": content, "emotion": emotion}可用于更精细的结果比对。
3.5 实践问题与优化
问题 1:页面加载不稳定导致失败
解决方案:增加显式等待 + 重试机制
page.wait_for_load_state("networkidle") # 等待网络空闲 expect(page.locator("#result")).to_be_enabled()问题 2:GPU 环境缺失导致推理缓慢
解决方案:在 CI 中设置超时阈值并启用缓存加速
timeout-minutes: 10问题 3:音频格式兼容性差异
解决方案:统一转换为 WAV 格式再测试
ffmpeg -i input.mp3 -ar 16000 -ac 1 output.wav4. 持续集成流程搭建
4.1 GitHub Actions 工作流配置
创建.github/workflows/ci.yml:
name: SenseVoice CI Pipeline on: push: branches: [ main ] pull_request: branches: [ main ] jobs: e2e-test: runs-on: ubuntu-latest container: nvidia/cuda:12.2.0-devel-ubuntu20.04 services: docker: image: docker:dind privileged: true env: DISPLAY: ":99" steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v4 with: python-version: '3.10' - name: Install dependencies run: | apt-get update apt-get install -y ffmpeg pulseaudio xvfb pip install -r requirements.txt pip install playwright pytest playwright install chromium - name: Start X virtual framebuffer run: Xvfb :99 -screen 0 1024x768x24 & - name: Launch SenseVoice App run: | nohup bash /root/run.sh > app.log 2>&1 & sleep 15 # 等待服务启动 tail -f app.log & - name: Wait for service ready run: | until curl -s http://localhost:7860; do echo "Waiting for server..." sleep 5 done - name: Run E2E Tests run: | python -m pytest test_sensevoice.py -v --capture=no - name: Upload screenshot on failure if: failure() uses: actions/upload-artifact@v3 with: path: results/test_success.png4.2 测试报告生成
可集成pytest-html生成可视化报告:
pip install pytest-html pytest test_sensevoice.py --html=report.html --self-contained-html并在 CI 中上传为 artifact。
4.3 通知机制(可选)
添加 Slack 或邮件通知:
- name: Notify on Failure if: failure() uses: 8398a7/action-slack@v3 with: status: ${{ job.status }} fields: repo,message,commit,author,action,eventName5. 最佳实践建议
5.1 分支保护策略
- 设置 PR 必须通过 CI 才能合并
- 要求至少一个 reviewer 批准
5.2 测试数据管理
- 将测试音频纳入版本控制(小文件)
- 使用
.gitattributes对二进制文件做差异化处理
5.3 性能监控延伸
未来可加入:
- 单次识别耗时统计
- CPU/GPU 占用率采集
- 内存泄漏检测
用于长期性能趋势分析。
6. 总结
6.1 实践经验总结
本文实现了SenseVoice Small WebUI 的自动化测试与 CI 集成全流程,涵盖:
- 使用 Playwright 实现端到端 UI 测试
- 构建标准化测试样本库
- 设计结构化结果校验逻辑
- 基于 GitHub Actions 搭建 CI 流水线
该方案已在实际开发中验证有效,显著提升了迭代效率与发布信心。
6.2 推荐建议
- 坚持“测试先行”原则:新功能上线前必须补充对应测试用例
- 定期维护测试样本:避免因模型升级导致旧样本失效
- 逐步推进测试覆盖率:从核心路径扩展到边界情况
通过持续集成机制,真正实现“改得放心、发得安心”。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。