news 2026/7/22 4:42:24

鸿蒙 PC Markdown 编辑器自动化测试:Playwright、ohosTest 与构建门禁

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
鸿蒙 PC Markdown 编辑器自动化测试:Playwright、ohosTest 与构建门禁

鸿蒙 PC Markdown 编辑器自动化测试:Playwright、ohosTest 与构建门禁

编辑器测试不能只验证应用能启动。真正的风险集中在用户数据:撤销是否跨文档、CRLF 是否保留、恶意 Markdown 是否进入 DOM、保存期间继续输入是否仍显示未保存、分栏滚动是否递归、五兆文档是否触发保护。只有把这些行为写成可重复断言,版本迭代才不会依赖一次次人工回忆。

本文基于鸿蒙 PC Markdown 编辑器 OhMarkdown,拆解 Web 内核、ArkTS 服务、模拟器证据与构建脚本组成的质量基线,说明哪些能力可以在 Linux Web Runner 验证,哪些必须依赖 DevEco Studio 与鸿蒙设备。完整代码位于 https://gitcode.com/VON-/codex_md_oh,本文对应提交3a9146e

测试分层由故障边界决定

OhMarkdown 不是纯 Web 页面,也不是纯 ArkUI 应用。编辑内核运行在 ArkWeb,文件、窗口、系统选择器和打印位于原生层。把所有测试都塞进模拟器会很慢,难以定位;只跑 Playwright又无法证明 HarmonyOS API可用。

当前质量体系分为四层:

  • Playwright验证 CodeMirror、Markdown 渲染、搜索、会话状态和 Web安全边界。
  • ohosTest验证 ArkTS 文档格式、文件写入故障恢复和大纲偏移。
  • Hvigor Debug、Release与 UnitTestBuild验证 ArkTS 编译、资源和 HAP产物。
  • MateBook Pro 2in1 模拟器验证系统选择器、强杀恢复、主题、文件树和桌面交互。

每层负责自己最接近的风险。正则替换不需要每次启动模拟器;文件夹授权不能只在 Chromium 中伪造;BOM字节一致应在 Core File Kit真实写入上测试;主题是否原生与 Web同屏一致需要设备截图。

这种分层不是追求测试种类,而是减少“测试通过但没有覆盖真实边界”。

Web 自动化运行真实生产逻辑

Web 编辑器使用 Vite 与 TypeScript构建,Playwright测试加载实际页面。测试前注入一个最小原生代理:

awaitpage.addInitScript(()=>{consthost=windowasunknownasEditorTestWindow;host.bridgeCalls=[];host.ohMarkdownBridge={onReady:()=>host.bridgeCalls.push({type:'ready'}),onState:(wordCount)=>host.bridgeCalls.push({type:'state',wordCount}),onChange:(wordCount,dirty)=>host.bridgeCalls.push({type:'change',wordCount,dirty}),onSnapshot:(content,revision)=>host.bridgeCalls.push({type:'snapshot',content,revision}),onCommand:(command,content)=>host.bridgeCalls.push({type:'command',command,content})};});

替身不实现 ArkTS业务,只记录 Web 发出的协议事件。测试可以断言中文输入后 onChange 字数、dirty、恢复快照 revision和保存命令正文。它不是把编辑器函数 mock掉,而是让真实 CodeMirror、定时器和渲染器运行。

awaitpage.goto('/');awaitpage.locator('.cm-editor').waitFor();

等待编辑器 DOM 而不是固定 sleep,降低不同机器上的时间波动。只有快照节流语义本身需要等待计时器,其余交互尽量依赖条件断言。

二十项回归覆盖的不是页面数量

当前 Web自动化包含二十项,覆盖以下主链路:

  • 源码、分栏和预览模式。
  • Markdown 净化和脚本不执行。
  • GFM表格、删除线、自动链接、只读任务列表。
  • 系统深色与显式主题覆盖。
  • 中文输入、撤销、重做和保存命令快照。
  • 两秒内恢复快照和恢复文档脏状态。
  • 新文档撤销历史、相同内容重做历史隔离。
  • 多标签正文、撤销和未保存状态隔离。
  • 大小写、整词、正则、当前替换和全部替换。
  • 标题偏移跳转与预览切回源码。
  • 双向同步滚动与关闭同步。
  • CRLF编辑语义。
  • 撤销回基线和保存后新基线。
  • 大文档保护。
  • 窄窗口分栏布局。
  • 安全独立 HTML导出和打印预览。
  • 生产包不引用外部子资源。

测试数量本身不是质量指标。二十项有价值,是因为每项对应一个可导致数据损坏、功能失效或安全退化的明确契约。后续新增测试应来自新需求、缺陷复现和风险分析,而不是为了提高数字。

脏状态必须用行为验证

编辑器保存基线最容易出现“星号只会亮、不会灭”。测试先设置基线、输入,再撤销:

awaitpage.evaluate(()=>host.OhMarkdownEditor.setDocument('基线'));awaitpage.locator('.cm-content').click();awaitpage.keyboard.insertText('修改');awaitpage.evaluate(()=>host.OhMarkdownEditor.undo());awaitpage.waitForTimeout(200);constcalls=awaitpage.evaluate(()=>host.bridgeCalls);expect(calls.at(-1)).toEqual({type:'change',wordCount:2,dirty:false});

断言 Bridge最后状态,而不是检查一个 Web内部变量。这样能证明 updateListener、Text基线比较和原生通知链共同生效。

保存后新基线用另一项测试:输入“已保存”,调用 requestCommand与 markSaved,再输入“后续”并撤销,最终 dirty应回到 false。这个路径覆盖保存请求时 Text快照,而不是只测初始打开。

多会话测试关注历史串线

多标签视觉可以人工看到,最严重错误却是撤销历史串线。自动化分别编辑 session-a和 session-b:

host.OhMarkdownEditor.setSessionDocument('session-a','文档甲');// 输入“修改”host.OhMarkdownEditor.activateSession('session-b','文档乙');// 输入“新增”

切回 a后撤销,正文必须变回“文档甲”;再切到 b,仍然是“文档乙新增”。这项用例同时证明 EditorState、正文与历史归属于 sessionId。

测试还需要继续增加选区、滚动和重做隔离。已有用例建立最低安全线,不意味着会话所有状态都已覆盖。测试报告应区分自动断言、调用链审查和模拟器操作,不能把三者混写成“全部自动化”。

安全测试直接检查危险结果不存在

Markdown 安全用例输入脚本:

constsource='# HarmonyOS Markdown\n\n'+'Hello **world**.\n\n'+'<script>'+'window.unsafeScriptExecuted=true'+'</script>';

预览后断言标题与加粗存在、script节点数量为零、全局标记未定义。不能只检查 DOM 没有脚本标签,因为脚本可能先执行再被清理;全局副作用断言补上执行层证据。

HTML导出还检查:存在 doctype和 CSP;标题、strong和本地图片保留;不存在 script、javascript:URI和外部 stylesheet。功能允许列表与危险拒绝列表同时验证,避免安全修复把正常 Markdown全部删掉。

生产包测试读取实际打进entry/src/main/resources/rawfile/editor/index.html的文件:

constproductionHtml=readFileSync(resolve(process.cwd(),'../entry/src/main/resources/rawfile/editor/index.html'),'utf-8');expect(productionHtml).not.toMatch(/<script[^>]+src=/i);expect(productionHtml).not.toMatch(/<link[^>]+rel=["']stylesheet["']/i);expect(productionHtml).toContain('OhMarkdownEditor');

这项检查锁住离线单文件约束。源码测试通过但构建产物仍引用 CDN,会在无网络鸿蒙 PC 上白屏;产物断言比检查 package.json更接近发布事实。

大文档测试验证降级而不是速度

Web用例创建五兆字符文档,尝试切到预览:

host.OhMarkdownEditor.setDocument('a'.repeat(5*1024*1024));host.OhMarkdownEditor.setMode('preview');

预期工作区仍为 source、编辑器可见、预览隐藏、Bridge字数为 -1、打印准备返回 false。测试锁定的是保护策略:超过边界不渲染、不统计、不打印。

它不证明十兆文件在三秒内加载,也不测内存。性能指标需要 Release模拟器记录读取、编辑器加载和进程内存。功能自动化与性能测试使用同一个边界常量,但证据形式不同。

ohosTest 验证 Core File Kit真实行为

文档字节一致不能只在 Node文件系统上测,因为产品使用 HarmonyOSfileIo、AtomicFile与 URI。ohosTest在应用沙箱创建文件,通过 Core File Kit读写。

原始 BOM与 CRLF 用例先读取十六进制:

constoriginal='\uFEFF# 鸿蒙 PC\r\n\r\n第一行\r\n第二行\r\n';awaitwriteRawText(testPath,original);constbeforeHex=awaitreadBytesAsHex(testPath);constopened=awaitreadUtf8Document(testPath);expect(opened.format.hasUtf8Bom).assertTrue();expect(opened.format.lineEnding).assertEqual(LineEnding.CRLF);awaitwriteUtf8Document(testPath,opened.content,opened.format);expect(awaitreadBytesAsHex(testPath)).assertEqual(beforeHex);

比较字节十六进制,而不是重新读取后只比较字符串。BOM是否保留只有字节层能确认。

故障注入用例删除目标目录制造写入失败,同时预先保存沙箱旧版本记录。写入失败后断言备份仍在,再重建目录并恢复旧内容。它验证“失败后可恢复”,而不是只断言 Promise抛错。

第四项 ohosTest验证 Markdown大纲:中文标题、Setext、代码围栏过滤和 UTF-16偏移。服务层纯函数可以快速跑,仍在 ArkTS运行时确认正则与字符串坐标。

统一脚本减少遗漏

Web验证脚本非常小:

#!/bin/shset-euROOT_DIR="$(CDPATH= cd -- "$(dirname--"$0")/.."&&pwd)" cd "$ROOT_DIR/web-editor"npmrun test:e2e

set -eu让任一命令失败立即退出,未定义变量也失败。脚本从自身位置计算根目录,不依赖调用者当前路径。

本机统一入口继续执行 Debug和 UnitTestBuild:

"$ROOT_DIR/scripts/verify-web.sh""$ROOT_DIR/scripts/build-debug.sh"cd"$ROOT_DIR""$DEVECO_HOME/tools/hvigor/bin/hvigorw"\UnitTestBuild\--modemodule\-pproduct=default\-pmodule=entry@default\-pbuildMode=test\-punitTestMode=true\--no-daemongitdiff--check

统一入口的价值不是少打几条命令,而是让开发者与流水线共享顺序,避免只跑最熟悉的一层。git diff --check阻止空白错误进入提交。

设备 ohosTest的安装和运行仍需要 HDC与模拟器,尚未完全并入脚本。后续可增加目标检测、测试 HAP安装、执行和结果提取,但脚本不能在没有设备时假装通过。

GitCode 流水线只承担 Web层

当前.gitcode-ci.yml配置使用 Playwright官方镜像:

stages:-testweb_editor_regression:stage:testimage:mcr.microsoft.com/playwright:v1.61.1-noblescript:-cd web-editor-npm ci--ignore-scripts-npm run test:e2e

缓存web-editor/node_modules/,key包含提交分支。Linux Runner可以验证 TypeScript、Vite与Chromium,不包含 DevEco Studio macOS环境,因此不能宣称鸿蒙 HAP也在 CI中通过。

截至本文基线,流水线配置已经入库,但远程 Runner首次执行结果尚未确认。准确说法是“CI配置已建立”,不是“远程流水线已通过”。质量文档把该项保持 In Progress,直到平台真实产生成功结果。

若 GitCode实际配置文件名、Runner权限或镜像拉取策略不同,需要根据远程日志修正。CI不是因为仓库里出现 YAML就自动成立。

版本化 Markdown 语料

项目保存四类基线文件:

  • commonmark-baseline.md:基础标题、段落、列表、引用、代码。
  • gfm-baseline.md:表格、删除线、链接和任务项。
  • outline-baseline.md:ATX、Setext、围栏与中文偏移。
  • security-baseline.md:脚本、危险协议和嵌入标签。

测试代码中的最小字符串便于定位,文件语料适合模拟器打开、人工比较和版本差异。每次发现缺陷,应把最小复现加入对应语料,再补自动断言。这样修复不会只存在于一次聊天或截图中。

语料需要保持小而有目的,不能把随机大型文档提交进测试目录。性能大文件可以在脚本运行时生成,避免仓库膨胀;字节语料则要明确 BOM和换行,普通编辑器保存它可能改变内容,因此最好由测试代码构造。

鸿蒙 PC 应用基线截图

下图来自 MateBook Pro 2in1模拟器,展示实际 HAP中的 ArkUI工作台与离线 CodeMirror编辑区。自动化最终保护的不是测试页面,而是这套进入鸿蒙 PC 应用的编辑能力。

应用截图是设备层证据之一,不替代自动化结果。每个关键用例保存对应截图或报告,才能在 UI变化、平台升级和回归失败时知道基线是什么。截图前还要清理个人路径和文档内容,技术证据不能制造隐私泄露。

测试结果与退出条件

提交3a9146e的本地基线为 Web 20/20、设备 ohosTest 4/4,Debug、Release与 UnitTestBuild成功。构建成功说明当前代码与 API 24工具链兼容,测试通过说明已覆盖契约在该环境成立。

但第二阶段仍不能仅凭这些数字结束。G2-08还要求远程 CI首次通过,并完成十名内部用户连续七天真实文档试用。自动化善于覆盖已知输入,内部使用会暴露文件来源、目录规模、输入法、窗口习惯和恢复路径中的未知组合。

质量门禁必须保留未完成项。把“测试全部通过”与“阶段退出条件全部满足”分开记录,能防止工程团队为了里程碑把外部验证悄悄改成可选项。

下一步应增加什么

当前基线仍缺少:保存并关闭选择器取消的设备自动化;多标签完整恢复;工作区两千项规模;系统主题前后台多轮切换;触控板同步滚动压力;自由窗口多档宽度;真实鸿蒙 PC而不只是2in1模拟器;崩溃恢复重复强杀;文件外部修改冲突;CI上的 ArkTS构建。

新增测试优先级应按数据损失和高频工作流排序。比如保存失败保留缓冲区比按钮悬停颜色更优先,多会话恢复比边缘 Markdown排版更优先。UI视觉回归也有价值,但不能挤占文件安全测试。

长期还需要记录性能分位数、崩溃率和恢复成功率。单次加载345毫秒不能代表所有设备;内部试用应匿名记录文档规模、操作结果和问题等级,不收集正文。

结语

OhMarkdown 的质量基线把编辑内核、原生文件服务、构建工具和模拟器分开验证,再通过统一脚本和版本化语料连接。Playwright锁定二十项 Web契约,ohosTest验证四项 Core File Kit与 ArkTS行为,Hvigor验证 HAP构建,模拟器完成系统交互证据。

这套体系最重要的特征是诚实:Web Runner不冒充鸿蒙构建,配置入库不冒充远程通过,四项服务测试不冒充全应用自动化,截图不冒充行为断言。鸿蒙 PC Markdown 编辑器要长期做大,质量不是发布前的一轮点击,而是每次改动都能重新回答“用户文档是否仍然安全”的工程能力。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/20 21:12:06

AM275x SoC ISC寄存器配置实战:硬件级内存访问控制与安全隔离

1. ISC寄存器在AM275x SoC中的核心作用与设计哲学在嵌入式系统&#xff0c;尤其是像TI AM275x这类高性能异构信号处理器的开发中&#xff0c;我们常常面临一个核心挑战&#xff1a;如何在复杂的多核、多主设备&#xff08;Master&#xff09;环境中&#xff0c;确保内存访问的有…

作者头像 李华
网站建设 2026/7/20 21:11:41

Wiselinks资源变更检测:如何实现自动页面刷新机制

Wiselinks资源变更检测&#xff1a;如何实现自动页面刷新机制 【免费下载链接】wiselinks If Turbolinks are not enough for you. Wiselinks makes your application work faster. 项目地址: https://gitcode.com/gh_mirrors/wi/wiselinks Wiselinks是一个让Web应用运行…

作者头像 李华
网站建设 2026/7/20 21:07:58

鸿蒙 ArkTS 实战:After Sales Ticket 从售后工单到电商运营工具完整解析

鸿蒙 ArkTS 实战&#xff1a;After Sales Ticket 从售后工单到电商运营工具完整解析 前言 After Sales Ticket 是一个基于鸿蒙 ArkTS 编写的电商运营类单页应用&#xff0c;核心场景是 售后问题处理。 它把 维护问题类型、图片证据、处理进度、处理结果和工单数量 这类运营动…

作者头像 李华
网站建设 2026/7/20 21:06:49

Speculative RAG框架:提升LLM检索生成效率与质量的双阶段机制

1. 项目概述&#xff1a;Speculative RAG框架的核心价值在大型语言模型&#xff08;LLM&#xff09;应用领域&#xff0c;检索增强生成&#xff08;RAG&#xff09;技术已经成为连接静态知识库与动态推理能力的关键桥梁。但传统RAG流程存在一个根本性矛盾&#xff1a;检索阶段需…

作者头像 李华
网站建设 2026/7/20 21:04:38

Godot引擎接入HarmonyOS分布式能力:体感游戏与多屏互动开发实践

1. 项目概述&#xff1a;当开源游戏引擎遇见分布式操作系统最近在独立游戏开发圈和鸿蒙生态开发者社区里&#xff0c;一个话题的热度正在悄然攀升&#xff1a;如何将Godot这款轻量、开源且功能强大的游戏引擎&#xff0c;与HarmonyOS的分布式能力结合起来&#xff1f;这不仅仅是…

作者头像 李华
网站建设 2026/7/20 21:02:08

继电器驱动电路设计与应用全解析

1. 继电器基础认知&#xff1a;从电磁铁到开关革命继电器本质上是一个用电磁铁控制的机械开关&#xff0c;这个看似简单的定义背后隐藏着电气控制史上的重大突破。1885年约瑟夫亨利发明的电磁继电器&#xff0c;最初是为了延长电报信号的传输距离&#xff0c;却意外成为了现代自…

作者头像 李华