Testing & CLI 测试与命令行

SXSEditor ships with a Mocha + Chai + Sinon + JSDOM test suite and a built-in CLI debug helper. The test suite covers ~1500 cases across 61 test files; the CLI lets you verify GPU detection, model loading, and end-to-end synthesis from a terminal without opening the GUI.

SXSEditor 内置 Mocha + Chai + Sinon + JSDOM 测试套件与 CLI 调试助手。测试套件覆盖 61 个测试文件、约 1500 个用例;CLI 让你在终端中验证 GPU 检测、模型加载与端到端合成,无需打开 GUI。

ℹ️

All test scripts are defined in package.json. The CLI entry point is src/main/cli.js, invoked via npm run cli. The CLI intentionally reuses the real pipeline code paths (not mocks) so it doubles as an integration smoke test.

所有测试脚本定义在 package.json 中。CLI 入口为 src/main/cli.js,通过 npm run cli 调用。CLI 有意复用真实管线代码路径(非 mock),因此兼作集成冒烟测试。

Test Framework 测试框架

Tool工具 Version版本 Role作用
Mocha ^11.7.6 Test runner, BDD interface (describe/it)测试运行器,BDD 接口(describe/it
Chai ^6.2.2 Assertion library (expect/should)断言库(expect/should
Sinon ^21.1.2 Spies, stubs, mocks; auto-restored sandbox per testspy、stub、mock;每条用例自动恢复 sandbox
JSDOM ^29.1.1 Simulates window/document for renderer code in Node在 Node 中为渲染进程代码模拟 window/document
nyc ^18.0.0 Code coverage (text + HTML reporter)代码覆盖率(text + HTML 报告器)
ESLint ^9.39.4 Static analysis / linting静态分析 / lint

Test Commands 测试命令

Command命令 Description说明
npm test Run the full suite once (spec reporter, 30s timeout)运行完整套件一次(spec 报告器,30 秒超时)
npm run test:watch Re-run on file change (watch mode)文件变更时重跑(watch 模式)
npm run test:coverage Run suite under nyc; prints text summary + writes HTML to coverage/在 nyc 下运行套件;打印文本摘要并输出 HTML 到 coverage/
npm run lint ESLint over src, test, scripts, *.config.jssrctestscripts*.config.js 跑 ESLint

The underlying Mocha invocation is:

底层的 Mocha 调用为:

mocha --require ./test/setup.js "test/**/*.test.js" --timeout 30000 --reporter spec

Test Setup (test/setup.js) 测试设置(test/setup.js

The setup file is required before every test file. It does four things:

该设置文件在每个测试文件之前被 require。它做四件事:

  1. Babel register@babel/register with @babel/preset-env transpiles ES module syntax (import/export) used by src/ on the fly, so Node's CommonJS test runner can load renderer code.Babel register— 带 @babel/preset-env@babel/register 即时转译 src/ 使用的 ES module 语法(import/export),让 Node 的 CommonJS 测试运行器能加载渲染进程代码。
  2. JSDOM globals — creates a JSDOM instance with pretendToBeVisual: true and assigns global.window, global.document, global.HTMLCanvasElement, and global.navigator.JSDOM 全局对象— 创建带 pretendToBeVisual: true 的 JSDOM 实例,并赋值 global.windowglobal.documentglobal.HTMLCanvasElementglobal.navigator
  3. Canvas mockHTMLCanvasElement.prototype.getContext returns a stub with no-op methods (fillRect, drawImage, arc, ...) and getImageData returning a zeroed Uint8ClampedArray. This lets canvas-consuming code run under Node without a real GPU.Canvas mockHTMLCanvasElement.prototype.getContext 返回一个空操作方法的 stub(fillRectdrawImagearc 等),getImageData 返回全零 Uint8ClampedArray。这让消费 canvas 的代码在 Node 下无需真实 GPU 即可运行。
  4. Sinon sandbox — a mochaHooks root hook plugin creates a fresh sinon.createSandbox() in beforeEach and restore() in afterEach, so spies/stubs never leak between tests.Sinon sandboxmochaHooks 根钩子插件在 beforeEach 创建新 sinon.createSandbox()、在 afterEach 调用 restore(),spy/stub 不会在用例间泄漏。

Test Suite Layout 测试套件结构

All test files live in test/ and match *.test.js. They are grouped by subsystem:

所有测试文件位于 test/,匹配 *.test.js。按子系统分组:

Subsystem子系统 Test Files测试文件
Inference pipeline推理管线 nativeSvsPipeline, pipelineIntegration, onnxModelLoading, vocoderChunked, preprocessing, postprocessingDSP, durationStats, textProcessing, float16Utils, languageDetection, mergePhonemenativeSvsPipelinepipelineIntegrationonnxModelLoadingvocoderChunkedpreprocessingpostprocessingDSPdurationStatstextProcessingfloat16UtilslanguageDetectionmergePhoneme
Audio音频 audioSegmentation, audioOutputManager, audioFormatUtils, resampleAudio, wavEncoderaudioSegmentationaudioOutputManageraudioFormatUtilsresampleAudiowavEncoder
Themes主题 themeManager, themeTokens, themeStorage, themeValidator, colorUtilsthemeManagerthemeTokensthemeStoragethemeValidatorcolorUtils
Pitch detection音高检测 rmvpePitchDetector, basicPitchrmvpePitchDetectorbasicPitch
Core / platform核心 / 平台 historyManager, utilsMisc, security, ipcChannels, modelPaths, midiParser, trackManagerhistoryManagerutilsMiscsecurityipcChannelsmodelPathsmidiParsertrackManager
Robustness / integration健壮性 / 集成 robustness, crossModuleIntegration, batchProcessingrobustnesscrossModuleIntegrationbatchProcessing
💡

To run a single test file, pass its path to mocha directly: npx mocha --require ./test/setup.js test/themeManager.test.js --timeout 30000. To focus a single describe/it, append .only.

运行单个测试文件:直接把路径传给 mocha:npx mocha --require ./test/setup.js test/themeManager.test.js --timeout 30000。聚焦单个 describe/it:追加 .only

Writing a Test 编写测试

A typical test uses the BDD interface with the auto-restored Sinon sandbox. Because test/setup.js already provides window/document and Babel transpilation, you can import renderer modules directly:

典型测试使用 BDD 接口与自动恢复的 Sinon sandbox。由于 test/setup.js 已提供 window/document 与 Babel 转译,可直接 import 渲染进程模块:

import { expect } from 'chai';
import themeManager from '../src/themes/themeManager.js';
import { BUILTIN_THEMES } from '../src/themes/builtins/index.js';

describe('themeManager.activate', () => {
  beforeEach(() => {
    themeManager.registerBuiltins(BUILTIN_THEMES);
  });

  it('injects tokens onto documentElement', () => {
    themeManager.activate('dark-aurora');
    const bg = document.documentElement.style.getPropertyValue('--bg-app');
    expect(bg).to.equal('#14141f');
  });

  it('fires theme-changed event', () => {
    let fired = false;
    const off = themeManager.on('theme-changed', () => { fired = true; });
    themeManager.activate('light-paper');
    expect(fired).to.be.true;
    off();  // unsubscribe
  });
});

CLI Debug Mode CLI 调试模式

The CLI is a lightweight agent-debug helper implemented in src/main/cli.js. It is designed for functional verification + log output, not for replacing GUI workflows. Invoke it with:

CLI 是 src/main/cli.js 中实现的轻量 agent 调试助手。其定位是功能验证 + 日志输出,不追求替代 GUI 工作流。调用方式:

# from source
npm run cli -- <command> [options]

# explicit help
npm run cli:help

# packaged build
SXSEditor.exe --cli <command> [options]

Exit codes: 0 = success, 1 = runtime error, 2 = argument error.

退出码:0 = 成功、1 = 运行时错误、2 = 参数错误。

CLI Commands CLI 命令

Command命令 Description说明 Options选项
help Show the help text显示帮助文本
version Print build info from build-info.json输出 build-info.json 中的构建信息
info Print app / runtime / path info输出应用 / 运行时 / 路径信息
gpu Run GPU / DirectML device detection执行 GPU / DirectML 设备检测
models List onnx_models, mark missing required files列出 onnx_models,标记缺失的必需文件
settings Dump current settings.json输出当前 settings.json
init-pipeline Initialize the SVS pipeline (verifies all 9 models load); prints elapsed time初始化 SVS 管线(验证 9 个模型全部可加载);输出耗时
synth Run a minimal synthesis and print audio stats (no file written by default)运行最小合成并输出音频统计(默认不写文件) --out <path.wav>, --steps <N>, --notes <json>, --bpm <N>

CLI Examples CLI 示例

Verify GPU detection and model loading:

验证 GPU 检测与模型加载:

npm run cli -- gpu
npm run cli -- models
npm run cli -- init-pipeline

Run a quick 4-step synthesis smoke test:

运行 4 步快速合成冒烟测试:

# default 2 Chinese notes, 4 diff steps, bpm 120
npm run cli -- synth

# write WAV output, 8 diff steps, custom notes
npm run cli -- synth --out ./test.wav --steps 8 --bpm 90 \
  --notes "[{\"pitch\":60,\"start\":0,\"duration\":1,\"lyric\":\"zh_a1\"},{\"pitch\":64,\"start\":1,\"duration\":1,\"lyric\":\"zh_a4\"}]"

The synth command prints sample count, sample rate, duration, peak, and mean of the resulting Float32Array. Default notes are two Chinese phonemes (zh_a1, zh_a4) at pitches 60 and 64. The default 4 diffusion steps give a fast smoke test; production uses DEFAULT_DIFF_STEPS=32.

synth 命令会输出结果 Float32Array 的采样数、采样率、时长、峰值与均值。默认音符为两个中文音素(zh_a1zh_a4),音高 60 与 64。默认 4 步扩散用于快速冒烟测试;生产环境使用 DEFAULT_DIFF_STEPS=32

⚠️

The CLI still launches the Electron app object (it needs app.getPath and the GPU detection modules). It does not open any window — the main process exits as soon as the command finishes. Make sure models are downloaded first (run the GUI once, or the models command will report all files missing).

CLI 仍会启动 Electron 的 app 对象(需要 app.getPath 与 GPU 检测模块)。它不会打开任何窗口——主进程在命令完成后立即退出。请先确保模型已下载(先运行一次 GUI,否则 models 命令会报告所有文件缺失)。

Linting Lint

ESLint 9 with the flat config scans src, test, scripts, and root config files (*.config.js):

ESLint 9 采用 flat config,扫描 srctestscripts 与根配置文件(*.config.js):

npm run lint
# eslint src test scripts *.config.js --ext .js

Fix automatically with npx eslint src test scripts *.config.js --ext .js --fix. The globals package (^17.7.0) provides environment globals for the config.

自动修复:npx eslint src test scripts *.config.js --ext .js --fixglobals 包(^17.7.0)为配置提供环境全局变量。

Contributing 参与贡献

  1. Fork & branch — create a feature branch off main.Fork 与分支— 从 main 拉取特性分支。
  2. Write tests — new features should come with tests under test/. Aim to keep coverage stable or improve it.编写测试— 新功能应配 test/ 下的测试。目标是保持或提升覆盖率。
  3. Lint & test locally — run npm run lint and npm test before pushing. Fix all lint errors.本地 lint 与测试— 推送前运行 npm run lintnpm test。修复所有 lint 错误。
  4. Smoke-test the CLI — if your change touches the pipeline, run npm run cli -- init-pipeline and npm run cli -- synth to verify end-to-end.CLI 冒烟测试— 若改动涉及管线,运行 npm run cli -- init-pipelinenpm run cli -- synth 验证端到端。
  5. Open a PR — describe the change, link any related issue, and note if models/docs need updating.提交 PR— 描述改动、关联相关 issue,并注明是否需要更新模型 / 文档。
ℹ️

Per the project's git rules: commit messages must be in English; back up (commit) before destructive changes; test after destructive changes and commit again once green; use npm run package:lite for packaging tests. See the workspace rules for the full checklist.

按项目 git 规则:commit message 必须用英文;破坏性修改前先提交备份;破坏性修改后必须测试,通过后再提交;打包测试用 npm run package:lite。完整清单见工作区规则。