【天体运行模拟|19】HarmonyOS ArkTS 回归测试实战:覆盖启动、空数据、异常输入和重复点击

发布时间:2026/9/1 15:14:31

【天体运行模拟|19】HarmonyOS ArkTS 回归测试实战:覆盖启动、空数据、异常输入和重复点击
【天体运行模拟19】HarmonyOS ArkTS 回归测试实战覆盖启动、空数据、异常输入和重复点击回归测试最容易退化成一张“点过首页、能打开详情”的清单。真正会在上架后暴露的问题往往发生在第二次动作快速点两次“查看结果”写出重复记录启动、暂停、再启动后出现两个计时器清除数据后页面仍显示旧收藏Preferences 尚未初始化时空数据被误判为读取失败窗口缩放后 Canvas 仍按旧尺寸绘制。“天体运行模拟”的真实代码包含四个一级 Tab、首页入口、关卡收藏、知识网格、个人中心、N 体模拟计时器、结果记录和本地数据清理。源码已经有一些防护启动模拟前调用stopTimer()页面消失时停止计时器滑块由min/max/step约束引力计算用最小距离平方避免除零清除数据前有不可恢复确认。但项目目录中未检索到现成测试用例因此不能把这些代码结构等同于“已经通过自动化回归”。本文面向 HarmonyOS 5.0 及以上版本基于真实页面和数据链建立从纯逻辑、页面状态、持久化到 release 包的回归测试方案重点覆盖启动、空数据、异常输入、重复点击与生命周期。项目基线应用版本1.0.0Bundle Name 为com.jiaweikan.one13目标设备包含 phone、tablet 与 2in1。文中测试代码为可落地的设计示例实际通过状态必须以本地或设备测试报告为准。一、回归目标先从用户主链路定义主链路不是页面列表而是用户能够完成的闭环安装并启动 → 首页选择实验 → 调整参数并启动模拟 → 暂停或查看结果 → 保存实验记录 → 收藏实验 → 返回关卡页复核收藏 → 设置页清除数据 → 重启后确认数据已清除 → 卸载任何版本只要改动 Canvas、DataStore、路由、主题或布局都可能影响这条链。回归用例应围绕闭环组织而不是按文件平均分配。二、建立测试层级层级适合验证速度纯逻辑测试物理计算、格式化、边界映射快服务测试Preferences、记录与清除中页面测试状态、点击、空页、路由中设备冒烟安装、启动、系统栏、生命周期慢多设备回归分屏、键鼠、窗口变化最慢不是所有逻辑都通过 UI 点一遍。物理公式和状态转换放到纯函数后可以快速覆盖大量边界系统生命周期和真实绘制必须在设备上验证。三、为每个用例写四个字段一个可重跑用例至少包含interface RegressionCase { id: string precondition: string action: string expected: string cleanup: string }例如“清除数据”不能只写“点击清除”。前置要准备收藏、笔记和记录动作要包含确认预期要同时检查 UI 与 Preferences清理要把测试环境恢复为空。四、冷启动与热启动分开冷启动验证应用进程不存在时的初始化热启动验证从后台恢复。两者会触发不同生命周期。冷启动检查首屏不白屏、不闪退状态栏和底部导航可读DataStore.init()完成前页面不误显示错误首页 Hero 和 Canvas 正常绘制四个 Tab 均可进入首次空数据没有残留占位内容。热启动还要检查模拟计时器、当前 Tab、未保存草稿和页面滚动状态是否符合产品预期。五、真实 Tabs 状态是第一组回归点Index.ets维护State currentIndex: number 0 private tabController: TabsController new TabsController()onChange更新索引首页还通过回调切换到关卡页。至少验证点击四个 Tab图标与文字选中态一致首页“关卡模式”能切到索引 1连续快速切换不会出现两个 Tab 同时选中从二级页返回后仍回到原 Tab横竖屏或窗口变化不把索引重置为 0。六、首页空数据不能只验证不崩溃HomePage默认通过getAllExperiments()获取实验并slice出热门列表。若未来数据源为空Grid 会自然没有项但页面是否给出空状态仍要定义。type ContentState | loading | empty | content | error空数组是业务状态读取失败是错误状态初始化未完成是 loading。回归测试要分别注入不能都验成一个空白区域。七、关卡页空收藏与空实验是两回事LabPage的favoriteIds默认空数组空收藏表示所有星标未选中experiments为空才表示没有关卡。测试应拆开有实验、无收藏列表完整星标为空有收藏对应 ID 星标选中收藏包含不存在 ID列表不崩溃实验为空显示明确空状态分类过滤后为空提示当前分类无内容而不是全局加载失败。这能发现“一个空数组承担多个语义”的问题。八、Preferences 初始化失败需要可观察DataStore 多处catch后返回默认值。默认值保护了页面不崩溃但也可能把读取异常伪装成空数据。测试环境应能注入interface FavoritesRepository { load(): Promisestring[] save(ids: string[]): Promiseboolean }页面测试替换成成功、空值、延迟和抛错实现验证 loading、empty、content、error 四态。没有依赖边界时异常测试会被静态 DataStore 调用绑住。九、模拟页启动按钮的真实防重逻辑源码的启动流程private startSimulation(): void { this.isRunning true this.stopTimer() this.drawCanvas() setTimeout(() { if (this.isRunning) { this.startTimer() } }, 120) }startTimer()内部再次调用stopTimer()这是防止多计时器的重要设计。回归测试要快速点击启动、暂停、启动并观察timerId始终只代表一个活动计时器暂停后位置不再变化再启动从当前状态继续页面退出后计时器停止延迟 120ms 的回调不会在暂停后重新启动。十、重复点击不能只看按钮文案按钮文案从“启动模拟”切为“暂停模拟”快速点击会在两个状态间切换。真正断言应针对可观察行为16ms 时间步只执行一次 body 位置增量不翻倍 学习时长不重复累计 退出后 CPU 不持续占用UI 文案正确但后台存在两个 interval仍是严重回归。十一、页面销毁必须释放资源真实代码在aboutToDisappear中this.stopTimer() this.persistLearningTime()需要验证三条路径系统返回、路由跳转到结果页、应用退后台。尤其是跳转结果页前可能仍在运行离开后 Canvas 更新和 interval 都必须停止。可以在测试构建中暴露只读诊断值interface SimulationDiagnostics { timerActive: boolean stepCount: number lastPersistedAt: number }release 构建不应保留敏感调试入口。十二、异常输入从滑块边界开始参数使用Slider({ value: this.paramValues[index], min: param.min, max: param.max, step: param.step })回归点包括最小值、最大值、非整数步长、快速拖动、窗口缩放中拖动和无障碍调整。每次onChange将值四舍五入到两位显示又根据step决定小数位需要验证内部值与显示值一致。十三、模型层还要防御非 UI 输入Slider 能约束正常交互但路由参数、旧数据或测试代码可能传入NaN、Infinity、负质量和越界速度。物理引擎边界不应只依赖组件。function normalizeMass(value: number): number { if (!Number.isFinite(value)) return 1 return Math.min(5000, Math.max(1, value)) }测试覆盖NaN、正负 Infinity、0、负数、边界两侧和超大值。归一化规则应与产品参数范围一致。十四、引力计算已有除零保护真实算法使用const distSq Math.max(dx * dx dy * dy, 90) const dist Math.sqrt(distSq) const force g / distSq当两个天体坐标相同距离平方不会变成 0。这条规则应建立单元测试同坐标不产生 NaN 或 Infinity极近距离加速度仍为有限值两体受力方向相反合并后总质量守恒合并后速度按动量加权半径不超过源码上限 34。十五、碰撞合并测试要验证不变量只断言“天体数量减少”不够。应验证totalMassAfter totalMassBefore momentumAfter ≈ momentumBefore one body marked inactive surviving body remains finite black hole type has priority bodyCount equals alive list length浮点比较使用误差范围不能直接用字符串或完全相等。十六、轨迹数组必须有上限源码中if (body.trailX.length 72) { body.trailX.shift() body.trailY.shift() }长时间运行测试应确认 X/Y 长度始终一致且不超过 72隐藏轨迹后不会继续无界增长重置系统后旧轨迹清除。否则几分钟冒烟正常长时间运行才出现内存和绘制问题。十七、越界天体清理天体超出 Canvas 外扩 200 的范围后标记alive false随后过滤数组。测试应覆盖四个方向、刚好边界和边界外一像素并确认删除后bodyCount更新绘制不再访问已删除天体全部天体离开后页面显示合理状态查看结果不会因空数组产生 NaN重置可恢复默认系统。十八、结果页重复点击是高风险点“查看结果分析”点击处理会this.persistRecord() DataStore.incrementExperimentCount() router.pushUrl({ url: resultUrl })这些异步动作没有等待也没有submitting防重。快速双击可能写入两条记录、计数两次或发起两个路由跳转。这是当前源码可以识别的回归风险不能说已经解决。建议State submittingResult: boolean falseprivate async openResult(): Promisevoid { if (this.submittingResult) return this.submittingResult true try { await this.persistRecord() await DataStore.incrementExperimentCount() await router.pushUrl({ url: resultUrl }) } finally { this.submittingResult false } }测试快速点击 2、5、10 次最终只能新增一条记录和一次计数。十九、收藏快速点击可能写回旧值实验页切换收藏时先读取数组、立即更新isFavorite再保存。两次点击并发可能都读取同一旧数组。回归测试要模拟慢存储并连续点击点击序列预期最终状态一次取反两次回到初始状态三次取反保存失败UI 回滚或明确失败若最终状态与点击奇偶不一致需要在仓库层串行整个读改写流程。二十、清除数据必须防重复确认设置页已经用AlertDialog告知不可恢复这是正确的破坏性操作边界。回归用例应验证点击取消不改数据点击确定清空所有指定键连续点击设置入口只出现一个有效对话框清除中按钮不可重复执行任一写入失败不显示“全部已清除”清除后收藏页、记录页和统计快照立即更新重启后数据仍为空。当前多次putString/putNumber顺序执行但异常被 DataStore 内部吞掉时页面仍可能 Toast 成功需通过返回结果改进。二十一、缓存清理与业务清理分开测设置页分别提供缓存清理和模拟数据清理。缓存目录为空、目录不可用、文件删除失败、嵌套目录和清理后重新计算大小都应覆盖。关键断言清缓存不能删除收藏、笔记和记录清模拟数据不能误删应用必要资源。名称相近的两个入口最容易在重构中调用错方法。二十二、路由参数异常实验页通过expId和expName接收参数。回归测试传入合法实验 ID缺失 ID空字符串未知 ID超长名称包含特殊字符的名称直接进入结果页但缺少统计参数。页面应使用明确默认实验或显示错误不应因强制类型转换白屏。默认值必须与产品预期一致。二十三、返回刷新与旧请求覆盖LabPage在aboutToAppear与onPageShow都调用reloadFavorites()。首次显示可能出现两个异步读取。测试让第一次读取延迟更长、返回旧值第二次快速返回新值确认旧请求不会最后覆盖新状态。可用版本号private reloadVersion: number 0private async reloadFavorites(): Promisevoid { const version this.reloadVersion const ids await DataStore.loadFavorites() if (version ! this.reloadVersion) return this.favoriteIds ids }二十四、窗口变化回归首页和知识页使用onAreaChange改网格列数。回归宽度至少覆盖599/600/601与839/840/841并连续拖动窗口。检查卡片无重叠或截断当前 Tab 不重置收藏和模拟状态不丢Canvas 清理并按新尺寸重绘小高度窗口所有操作可滚动到2in1 鼠标和键盘仍可操作。二十五、视觉回归不能只比全屏像素Canvas 轨道会随时间变化整页像素比较容易误报。建议分区静态导航、卡片和文字做截图差异Canvas 只检查非空、尺寸、关键颜色和无异常覆盖动态数字使用区域遮罩或语义断言深浅色分别建立基线phone、tablet、2in1 保存独立基线。截图差异必须由人工复核后更新不能失败就自动覆盖基线。二十六、构造可重复测试数据测试不应依赖开发者设备上已有收藏。每个用例前注入固定数据interface RegressionFixture { favorites: string[] notes: TestNote[] records: TestRecord[] experimentCount: number learningSeconds: number }用例结束后恢复或清空。数据 ID、时间戳和排序要固定避免结果随当前时间变化。二十七、回归证据结构化保存每次 release 候选包记录版本名 / versionCode 构建时间与提交号 设备型号与系统版本 安装包哈希 用例 ID 与结果 失败截图和日志 修复提交 复测结果“我刚才点过了”不能支撑发布决策。证据使失败可复现也避免下一轮重复调查。二十八、发布门禁只有以下条件同时满足才进入上架本地硬检查与构建通过纯逻辑关键边界测试通过四 Tab 和主实验闭环通过空数据、读取失败和异常参数有明确结果重复点击不产生重复写入或路由页面退出后无活动计时器清除数据后重启仍为空phone、tablet、2in1 目标布局通过release 包完成安装、启动、核心流程和卸载所有失败有归属阻断问题为零。不能用“调试预览正常”替代 release 包冒烟。二十九、推荐的最小自动化集合第一阶段不必追求全量 UI 自动化先落地高价值集合resolveSizeClass边界物理步进有限值碰撞质量与动量不变量轨迹长度上限收藏奇偶点击结果提交防重DataStore 空值、损坏 JSON 与写入失败清除数据覆盖所有键启停计时器唯一性冷启动主路由冒烟。这十项能覆盖最容易复发且影响较大的问题。三十、当前源码的风险清单风险当前证据回归策略结果重复提交点击中无防重状态高频点击断言单条记录收藏并发覆盖读改写未整体串行慢存储与奇偶点击清除假成功多次写入无汇总结果注入一次写失败空数据伪装错误catch 后默认空数组注入异常并检查 error双生命周期读取两处 reload乱序响应测试Canvas 尺寸变化动态绘制依赖宽高连续缩放与像素检查计时器泄漏依赖 stopTimer启停、退出与后台测试风险清单来自代码结构不代表线上已发生也不能虚构测试通过。三十一、上架前回归清单[ ] 冷启动、热启动和后台恢复通过[ ] 四个 Tab 与首页快捷切换通过[ ] loading、empty、content、error 四态可区分[ ] Slider 最小、最大和步长正确[ ] NaN、Infinity、负数不会进入物理核心[ ] 同坐标天体不产生非有限值[ ] 碰撞质量和动量满足不变量[ ] 轨迹长度不超过 72[ ] 启停和退出后只有零个或一个计时器[ ] 结果和收藏重复点击符合预期[ ] 清除数据取消、成功和失败路径完整[ ] 返回刷新不被旧请求覆盖[ ] 多窗口与三类设备布局可达[ ] release 包安装、启动、运行和卸载正常。总结高质量回归测试不是把页面点一遍而是把真实代码中的状态边界变成可重复断言启动要区分冷、热生命周期空数据要区分加载、错误异常参数要在模型层归一化重复点击要验证写入和路由只有一次页面退出要证明计时器已经释放。“天体运行模拟”已有不少值得保留的防护包括计时器启动前主动停止、离页释放、滑块范围、最小距离平方和轨迹长度上限。下一步应把这些隐含规则固化为纯逻辑、页面、持久化和 release 设备四层用例并优先补齐结果提交、收藏读改写、清除结果与乱序刷新等高风险回归点。本文唯一标记CSDN-SERIES:ALL-163201431AI 辅助声明本文部分内容由 AI 辅助整理源码事实、工程边界与风险结论均依据文中所列项目文件复核未实际执行的测试不标记为通过。

相关新闻

虚拟内存深度解析:从原理到配置,解决内存不足与性能优化

虚拟内存深度解析:从原理到配置,解决内存不足与性能优化

2026/9/1 15:14:31

1. 这篇文章真正要解决的问题 如果你是一名开发者,或者经常需要运行大型软件、本地AI模型,那么你一定遇到过这样的场景:程序运行到一半,突然弹出一个“内存不足”的错误,或者整个系统变得异常卡顿,甚至直接…

触宝校招后端大数据笔试全解析:从Java到Spark的实战复盘

触宝校招后端大数据笔试全解析:从Java到Spark的实战复盘

2026/9/1 15:14:31

1. 触宝校招笔试概览:一场没有硝烟的技术摸底 2017年秋季,触宝科技的校招笔试走到第二批,岗位锁定“后端大数据”方向。坦白讲,当时看到这个岗位名字心里就明白,这绝不是单纯考Java或者单纯考Hadoop,而是要…

TCPIP协议

TCPIP协议

2026/9/1 15:04:31

TCP/IP协议 文章目录TCP/IP协议IPIP地址NAT原理IP协议TCP协议TCP报文头部三次握手四次挥手TCP完整通信全流程TCP/IP四层模型总结IP 先来给大家讲讲IP协议,IP是什么? 为什么叫IP,IPInternet Protocol网际协议,IP地址就是互联网上…

从AI修图到工程化:构建稳定批量图片处理流水线的完整指南

从AI修图到工程化:构建稳定批量图片处理流水线的完整指南

2026/9/1 16:24:34

昨晚,我盯着屏幕,看着那个“正在处理”的进度条从1%缓慢地爬到99%,然后……卡住了。这已经不是第一次了。从一张简单的产品图抠图,到批量处理几百张活动照片,从调整色调到智能填充背景,我几乎把所有能找到的…

ch-皖星:将视频加载等待转化为品牌互动的前端解决方案

ch-皖星:将视频加载等待转化为品牌互动的前端解决方案

2026/9/1 16:24:34

最近在开发视频类应用时,你是否遇到过这样的困境:用户点击播放后,面对一个干巴巴的“加载中”转圈动画,耐心迅速流失,最终导致播放失败或用户直接离开?传统的加载状态设计,往往只关注技术层面的…

OpenClaw 卸载完全指南:从清理到彻底移除

OpenClaw 卸载完全指南:从清理到彻底移除

2026/9/1 16:24:34

1. 引言OpenClaw 是一款功能强大的开源 AI 助手框架,但当你需要更换工具链、释放磁盘空间或解决环境冲突时,彻底卸载就显得尤为重要。本文将从二进制文件、配置目录、依赖包、系统服务等多个层面,详细介绍如何在 Linux、macOS 和 Windows 上完…

告别造假数据,直接连数据库查真实时序数据喂给TimechoAI大模型

告别造假数据,直接连数据库查真实时序数据喂给TimechoAI大模型

2026/9/1 16:24:34

告别造假数据,直接连数据库查真实时序数据喂给TimechoAI大模型前面三篇文章,我们其实都在做一件事情。那就是在本地用代码造假数据。我们造了CPU的数据,造了内存的数据,然后把这些假数据拼成一个长长的字符串,扔给Time…

基于ROS与Python的点焊机器人仿真与控制课程设计全解析

基于ROS与Python的点焊机器人仿真与控制课程设计全解析

2026/9/1 16:24:34

简介:本资源是一套面向高校自动化、机器人工程及相关专业本科生的ROS课程设计实践项目,聚焦机械臂在ROS环境下的运动仿真与点焊工艺控制,解决课程设计中缺乏完整可运行案例的问题。压缩包共57个文件,涵盖12个launch启动脚本&#…

龙架构双周会“生肉”学习法:交叉编译与QEMU运行实践

龙架构双周会“生肉”学习法:交叉编译与QEMU运行实践

2026/9/1 16:14:34

如果你也在关注龙架构(LoongArch)生态,应该经常遇到一类“生肉”技术资源:官方双周会以原声录像的形式发布,没有中文字幕,信息密度又高。2026 年 8 月 6 日的第 7 期双周会就是这样一场硬核内容。很多人点开…

备战数据库管理工程师校招:索引、事务、备份恢复核心考点解析

备战数据库管理工程师校招:索引、事务、备份恢复核心考点解析

2026/9/1 1:53:39

每年校招季我都会接触不少准备数据库方向笔试的同学,看到最多的状态就是:简历上写着“熟悉 MySQL”“了解索引优化”,一碰到数据库管理工程师的笔试卷,却在索引、事务、锁、备份恢复这些题目上翻车。网易这套 2018 校园招聘数据库…

数字电路时序基石:深入理解建立时间与保持时间

数字电路时序基石:深入理解建立时间与保持时间

2026/9/1 9:55:14

1. 这不是“背公式”的事:时间参数到底在约束什么你翻过数字电路教材,一定见过这两个词:建立时间(Setup Time)和保持时间(Hold Time)。它们常被并列写在触发器(Flip-Flop&#xff09…

蓝桥杯国赛超声波测距机:从单片机原理到嵌入式系统实战

蓝桥杯国赛超声波测距机:从单片机原理到嵌入式系统实战

2026/8/31 17:18:46

1. 项目缘起:从赛题到超声波测距机的诞生第八届蓝桥杯单片机设计与开发国赛的题目,我至今记忆犹新。它没有直接给出一个花哨的名字,而是用“超声波测距机”这个朴实无华的功能描述,精准地勾勒出了考核的核心。对于当时备赛的我而言…

远程协作的工作台整理

远程协作的工作台整理

2026/9/1 0:03:36

远程协作的工作台整理远程协作的核心不是再加一个工具,而是让交接信息足够完整。异步任务要写明目标、输入位置、完成标准和需要决策的人。 工作台的最小配置 将日程、待办、代码和沟通入口收拢到少数固定位置;通知按紧急程度分层。工作台不需要模仿办公…

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

2026/9/1 0:03:36

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

2026/9/1 0:03:36

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

远程协作的工作台整理

远程协作的工作台整理

2026/9/1 0:03:36

远程协作的工作台整理远程协作的核心不是再加一个工具,而是让交接信息足够完整。异步任务要写明目标、输入位置、完成标准和需要决策的人。 工作台的最小配置 将日程、待办、代码和沟通入口收拢到少数固定位置;通知按紧急程度分层。工作台不需要模仿办公…

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

2026/9/1 0:03:36

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

2026/9/1 0:03:36

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…