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.js对 src、test、scripts、*.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。它做四件事:
- Babel register —
@babel/registerwith@babel/preset-envtranspiles ES module syntax (import/export) used bysrc/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 测试运行器能加载渲染进程代码。 - JSDOM globals — creates a JSDOM instance with
pretendToBeVisual: trueand assignsglobal.window,global.document,global.HTMLCanvasElement, andglobal.navigator.JSDOM 全局对象— 创建带pretendToBeVisual: true的 JSDOM 实例,并赋值global.window、global.document、global.HTMLCanvasElement、global.navigator。 - Canvas mock —
HTMLCanvasElement.prototype.getContextreturns a stub with no-op methods (fillRect,drawImage,arc, ...) andgetImageDatareturning a zeroedUint8ClampedArray. This lets canvas-consuming code run under Node without a real GPU.Canvas mock—HTMLCanvasElement.prototype.getContext返回一个空操作方法的 stub(fillRect、drawImage、arc等),getImageData返回全零Uint8ClampedArray。这让消费 canvas 的代码在 Node 下无需真实 GPU 即可运行。 - Sinon sandbox — a
mochaHooksroot hook plugin creates a freshsinon.createSandbox()inbeforeEachandrestore()inafterEach, so spies/stubs never leak between tests.Sinon sandbox—mochaHooks根钩子插件在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, mergePhonemenativeSvsPipeline、pipelineIntegration、onnxModelLoading、vocoderChunked、preprocessing、postprocessingDSP、durationStats、textProcessing、float16Utils、languageDetection、mergePhoneme |
| Audio音频 | audioSegmentation, audioOutputManager, audioFormatUtils, resampleAudio, wavEncoderaudioSegmentation、audioOutputManager、audioFormatUtils、resampleAudio、wavEncoder |
| Themes主题 | themeManager, themeTokens, themeStorage, themeValidator, colorUtilsthemeManager、themeTokens、themeStorage、themeValidator、colorUtils |
| Pitch detection音高检测 | rmvpePitchDetector, basicPitchrmvpePitchDetector、basicPitch |
| Core / platform核心 / 平台 | historyManager, utilsMisc, security, ipcChannels, modelPaths, midiParser, trackManagerhistoryManager、utilsMisc、security、ipcChannels、modelPaths、midiParser、trackManager |
| Robustness / integration健壮性 / 集成 | robustness, crossModuleIntegration, batchProcessingrobustness、crossModuleIntegration、batchProcessing |
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_a1、zh_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,扫描 src、test、scripts 与根配置文件(*.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 --fix。globals 包(^17.7.0)为配置提供环境全局变量。
Contributing 参与贡献
- Fork & branch — create a feature branch off
main.Fork 与分支— 从main拉取特性分支。 - Write tests — new features should come with tests under
test/. Aim to keep coverage stable or improve it.编写测试— 新功能应配test/下的测试。目标是保持或提升覆盖率。 - Lint & test locally — run
npm run lintandnpm testbefore pushing. Fix all lint errors.本地 lint 与测试— 推送前运行npm run lint与npm test。修复所有 lint 错误。 - Smoke-test the CLI — if your change touches the pipeline, run
npm run cli -- init-pipelineandnpm run cli -- synthto verify end-to-end.CLI 冒烟测试— 若改动涉及管线,运行npm run cli -- init-pipeline与npm run cli -- synth验证端到端。 - 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。完整清单见工作区规则。