鸿蒙 PC Markdown 编辑器测试设计:字节语料覆盖文本保真 鸿蒙 PC Markdown 编辑器测试设计字节语料覆盖文本保真Markdown编辑器最危险的回归往往肉眼看不出来。BOM消失、CRLF变成 LF、末尾换行增加、非法 UTF-8被替换字符吞掉预览可能完全相同Git却显示整文件变化。测试语料必须同时覆盖 Markdown语义和底层字节而不是只准备几篇“看起来复杂”的文章。本文基于 OhMarkdown说明如何组织 CommonMark、GFM、大纲、安全与字节格式语料如何区分文件 fixture和运行时构造以及怎样用十六进制比较验证未编辑保存。代码位于 https://gitcode.com/VON-/codex_md_oh对应提交3a9146e。语料按风险分类项目保留四份可读 Markdown基线test-fixtures/markdown/ commonmark-baseline.md gfm-baseline.md outline-baseline.md security-baseline.mdCommonMark覆盖标题、强调、代码、链接、引用和列表GFM覆盖表格、任务项、删除线和裸链接大纲覆盖 ATX、Setext、普通正文井号和围栏伪标题安全语料包含 script、javascript协议、iframe和允许的相对图片。分类让失败可定位。若表格消失先检查 GFM插件若围栏标题进入大纲检查解析状态机若脚本进入 DOM检查净化链。把全部语法塞进一个大文件测试失败只知道“页面不同”。可读 fixture 与字节 fixture 分工普通.md文件适合代码审查、模拟器打开和截图但 BOM、CRLF和 Mixed可能被开发者编辑器自动转换。关键字节语料由 ohosTest在运行时构造constoriginal\uFEFF# 鸿蒙 PC\r\n\r\n第一行\r\n第二行\r\n;awaitwriteRawText(testPath,original);字符串明确写出 UFEFF与\r\n测试文件每次在应用沙箱生成不依赖 Git checkout的 autocrlf。Mixed语料同样显式awaitwriteRawText(testPath,第一行\r\n第二行\n第三行\r);可读 fixture验证语法内容运行时 fixture验证编码字节两者不能互相替代。CommonMark 基线保持最小# CommonMark 基线 普通文本、**粗体**、*斜体*、行内代码 与链接。 引用内容 1. 有序列表 - 无序列表 ts const platform: string HarmonyOS PC;最小基线不追求覆盖整个规范而是锁住产品承诺的高频结构。每次遇到解析缺陷新增一个最小复现。语料太大时依赖升级产生差异难以判断是预期还是回归。 代码围栏本身要包含反引号和语言标记验证预览不会把内部内容当 Markdown。链接目标使用稳定示例域名但自动化不发网络请求。 ## GFM 基线验证扩展边界 md | 能力 | 状态 | | --- | --- | | 表格 | 完成 | | 任务列表 | 完成 | - [ ] 待处理任务 - [x] 已完成任务 ~~已废弃内容~~ https://example.com/gfm同一文件包含四项可在模拟器一次观察。Playwright不只比较截图而是断言 table、s、a和 checkbox结构任务复选框 disabled与 checked状态同时验证。后续扩充应加入对齐列、转义管道、嵌套任务和带括号 URL但每个边缘项最好有独立断言。语料负责复现测试负责解释预期。大纲语料故意制造伪标题正文中的 # 不是标题。 Setext 一级标题 md # 代码围栏中的标题必须忽略只放正常 # A无法证明解析器会排除错误输入。正文内井号、Setext与围栏标题同时出现才能覆盖行首规则、前瞻和围栏状态。 设备测试再加入中文并比较 UTF-16 offset ts expect(headings[2].offset).assertEqual( content.indexOf(### 目标标题) );中文让 UTF-8字节与字符串索引分离能发现坐标单位错误。安全语料同时包含允许项scriptwindow.fixtureScriptExecuted true/script [危险链接](javascript:alert(blocked)) iframe srchttps://example.com/iframe ![允许的相对图片](./assets/example.png)安全测试不能只输入危险内容。相对图片是允许能力净化后应保留安全 src和 alt。如果修复通过把所有标签属性删除危险消失但功能也坏了。拒绝列表和允许列表必须同场验证。还应增加 style、form、object、embed、事件属性、data URI与编码协议变体。每个新增渲染插件都要重新跑安全语料。字节读取辅助函数测试使用 Core File Kit读取全部字节转十六进制asyncfunctionreadBytesAsHex(path:string):Promisestring{constfileawaitfileIo.open(path,fileIo.OpenMode.READ_ONLY);try{conststatawaitfileIo.stat(file.fd);constdatanewArrayBuffer(stat.size);constbytesReadawaitfileIo.read(file.fd,data,{length:stat.size});constbytesnewUint8Array(data,0,bytesRead);letresult;for(letindex0;indexbytes.length;index1){resultbytes[index].toString(16).padStart(2,0);}returnresult;}finally{awaitfileIo.close(file);}}十六进制字符串便于 Hypium比较不受文本解码影响。测试规模很小字符串拼接成本可接受大文件可比较哈希而不是生成两倍长度文本。未编辑保存的黄金断言constbeforeHexawaitreadBytesAsHex(testPath);constopenedawaitreadUtf8Document(testPath);awaitwriteUtf8Document(testPath,opened.content,opened.format);expect(awaitreadBytesAsHex(testPath)).assertEqual(beforeHex);这是文本保真的核心打开后不修改以检测格式保存字节完全一致。正文字符串比较无法证明 BOM和换行。测试还断言内存正文不含 BOM、format标记 true、lineEnding为 CRLF。字节与语义双重断言能定位是读取模型还是序列化出错。Mixed 语料验证明确转换Mixed不要求未编辑后自动统一。测试指定目标 LF保存后正文必须全部使用\n再检测为 LF。另一个对称用例应指定 CRLF断言没有\r\r\n。UI层还需测试 Mixed修改后弹出策略对话框取消不保存LF/CRLF分别更新状态栏。服务测试验证转换函数模拟器验证用户决策。非 ASCII 与块边界读取器64 KiB分块并使用 streaming TextDecoder。语料应让三字节中文或四字节emoji跨块边界用填充字符把多字节序列首字节放在块末。fatal: true下若 stream配置错误会抛出正确实现能跨块组合。还应覆盖组合字符、代理对、空文件、只有 BOM、无末尾换行、多个末尾换行和超长单行。文本编辑器不能只测试中文常用字和英文。非法 UTF-8 应拒绝严格读取不应把非法字节替换为 UFFFD后允许保存因为原字节将不可恢复。测试应直接写入非法序列断言readUtf8Document失败、当前编辑会话不被替换、文件未修改。这类语料无法可靠保存为普通 Markdown源码应以 Uint8Array在测试中构造。错误信息不应打印文件正文。文件变化和短读语料读取器比较实际总字节与 stat.size。要验证“读取期间变化”需要测试替身或并发修改文件断言不返回半文档。写入则可注入目标目录删除验证备份保留。故障语料不是内容文件而是文件系统状态不存在目录、无权限、短写、备份清理失败。测试计划应把内容矩阵与故障矩阵交叉而不是只列语法。鸿蒙 PC 应用中的格式语料下图来自模拟器格式测试文档进入真实编辑器状态栏显示 UTF-8与换行。应用画面证明 fixture可由用户路径打开字节断言由设备测试完成。文章和报告中的截图应使用无敏感内容的专用语料不用真实用户文件。图片只记录应用状态不作为字节证明。版本管理规则可读 fixtures同步仓库成为代码评审的一部分技术文章目录本地忽略截图不影响测试。字节语料生成逻辑同步测试代码。修改 fixture必须说明预期变化不能在依赖升级时直接接受全部新快照。如果未来引入视觉快照应对字体和平台差异设置容忍结构断言仍是主要契约。测试文件名称表达语义不用test1.md。当前边界现有四份可读语料仍较小非法 UTF-8、块边界、CRLF目标归一和两千项目录规模需要继续补充。设备字节测试当前三项尚未形成完整参数化矩阵。结语Markdown测试语料必须覆盖看得见的语法和看不见的字节。OhMarkdown用分类文件锁定 CommonMark、GFM、大纲与安全用运行时构造锁定 BOM、CRLF、Mixed和故障状态再以十六进制比较验证保真。语料的价值不在数量而在每一份都对应明确风险、可重复预期和真实运行层。这样鸿蒙 PC编辑器升级解析器或 SDK时才能知道改变的是排版还是用户文件本身。每次线上或内部试用发现新的格式异常都应先把最小字节复现固化再修改实现没有进入语料库的修复很容易在下一次工具链升级时重新出现。