文档管理中心
|

HarmonyOS测试服务

我的完美桌面时钟品质蜕变之旅——从"能用"到"好用"的进阶之路

一、最开始,我以为它已经“差不多了”

《完美桌面时钟》是一款基于 HarmonyOS 6 开发的时间展示应用。

它的初衷其实很简单:让手机在更多场景下,真正变成一块好看、稳定的桌面时钟。

应用支持全屏时间展示、多种时钟样式和主题配置,也结合了 HarmonyOS 的组件能力,在功能层面已经比较完整。

在第一个可用版本完成时,我一度觉得:“至少已经能正常使用了。”

但随着内部测试和真实设备使用时间拉长,一些问题开始慢慢显现出来,而且这些问题恰恰是桌面时钟这种应用最不能忽视的

二、问题不是“不能用”,而是“不够安心”

和很多工具类应用不同,桌面时钟的使用场景有几个非常典型的特点:

启动频繁、展示时间长、用户容忍度极低。

在测试过程中,我陆续遇到了一些情况:

  • 在切换时钟样式或系统状态变化时,偶尔会看到 UI 闪一下

  • 冷启动进入主界面的速度,在部分机型上明显偏慢

  • 应用长时间运行后,偶发异常退出,但本地很难稳定复现

  • 不同设备、不同分辨率下,表现并不完全一致

这些问题单独看都不算“致命 Bug”,但叠加在一起,就会让人对一款桌面时钟是否适合长期使用产生怀疑。

这也让我意识到:光靠功能实现,是支撑不了“好用”这件事的。

于是,我开始完整地引入 HarmonyOS 官方测试体系,对《完美桌面时钟》进行了一次真正意义上的“质量重构”。

三、使用 DevEco Testing:从体验和性能入手,找出“卡”的根因

最先解决的是用户最直观感受到的问题:界面不够丝滑。

我在 DevEco Testing 中对应用进行了性能专项测试和稳定性测试,重点关注以下几个场景:

应用冷启动、时钟样式切换、桌面组件刷新、设置页面列表滑动。

先进行配置如下:

注意,要先连接好手机,app已经安装就在软件中选择已安装的应用,然后找到自己要测试的应用。如果没有安装也可以上传安装包。

创建任务后,软件开始执行测试任务。

测试报告很快给出了明确反馈:

总体来说性能还可以。测试项目都达标了。不过应用启动阶段存在主线程负载偏高的问题;某些自定义时钟样式在首次渲染时存在不必要的重复计算;设置页列表滚动时偶发掉帧。

这些问题如果靠“肉眼感觉”很难准确定位,但通过 DevEco Testing 的性能报告,可以直接看到启动耗时分布、卡顿发生的具体时间点以及对应调用栈。这让我迅速将优化目标聚焦到启动阶段逻辑拆分和 UI 渲染路径简化上。

优化完成后再次测试,启动耗时和掉帧次数都有明显下降,整体体验改善非常直观。

四、使用 DevEco Testing Hypium:把“容易出错的操作”交给自动化

随着功能增多,《完美桌面时钟》的配置项也越来越复杂:

不同样式切换、亮度模式变化、横竖屏适配、桌面组件更新频率调整……这些场景如果每次都靠手动回归,很容易遗漏。

于是我引入了 DevEco Testing Hypium,编写了一组 UI 自动化测试脚本,覆盖以下核心路径:

应用启动 → 进入设置 → 切换多种时钟样式 → 返回桌面 → 刷新组件 → 再次进入应用。

Hypium使用环境很重要:

  • Python环境推荐从Python官网安装Python3.10版本;
  • PyCharm环境推荐从PyCharm官网安装2022.3以后的社区版本(项目创建功能只支持2022.3至2025.1的Pycharm版本。2024.3版本由于pycharm自身原因,只能选择单设备模板进行创建);
  • hdc环境请参考调试工具-hdc中环境准备章节来安装和配置hdc环境;
  • 安装Hypium推荐PyPI在线安装:pip install hypium -U ;
  • DevEco Testing Hypium插件安装;

测试脚本工程创建:

直接使用以下附件中的模板工程:模版

工程目录文件:

收起
自动换行
深色代码主题
复制
HypiumProjectTemplate
|     |----aw                                     // 工程中自定义模块文件夹
|     |     |----Utils.py                           // 示例模块文件
|     |----config                                   // 测试工程配置文件夹
|     |     |----user_config.xml                    // 测试工程配置文件
|     |----resource                              // 测试资源文件夹,测试过程中用到的资源文件默认会优先从当前文件夹进行查找。
|     |----testcases                             // 测试用例文件夹,测试过程中的测试用例文件优先会从当前文件夹进行查找。
|     |    |----Example.json                        // Example测试用例配置文件,配置用例所需设备等参数。
|     |    |----Example.py                          // Example测试用例文件,存储测试逻辑代码。注意该文件无法直接运行,要通过测试框架启动后加载执行,详情参见后文测试用例执行部分。
|     |----main.py                               // 测试用例执行入口文件,用户可以通过运行该文件启动测试任务,执行测试用例。

工程配置文件:

收起
自动换行
深色代码主题
复制
<?xml version="1.0" encoding="UTF-8"?>
<user_config>
    <environment>
        <!-- type: 设备连接方式,仅支持设置为usb-hdc,表示使用hdc命令控制设备(默认)。 -->
        <device type="usb-hdc">
            <!-- ip: 远端hdc server的ip地址,ip和port为空时使用本地设备,非空时使用远端设备。 -->
            <!-- port: 远端hdc server的端口号 -->
            <!-- sn:设备序列号,设为空时,表示所有设备均可用 -->
            <info ip="" port="" sn="sn"/>
            <!-- 可添加多个info标签,配置多个设备 -->
            <info ip="" port="" sn="sn"/>
        </device>
    </environment>
    <testcases>
        <!-- 测试用例目录,该属性为空时默认使用为当前项目下的testcases目录。 -->
        <dir></dir>
    </testcases>
    <resource>
        <!-- 测试资源文件目录,该属性为空时默认使用为当前项目下的resource目录。 -->
        <dir></dir>
    </resource>
    <!-- 用例执行日志级别,当前仅支持设置为INFO或者DEBUG,默认为INFO,如需更详细信息可设置为DEBUG。 -->
    <loglevel>DEBUG</loglevel>
    <devicelog>
        <!-- 指定用例执行完成后自动从设备端拉取的文件目录,多个目录使用分号分隔。 -->
        <dir>/data/log/tee;/data/log/test</dir>
        <!-- 设置用例执行时抓取的hilog日志等级,默认值为INFO。 -->
        <loglevel>DEBUG</loglevel>    
        <!-- 设置单个用例执行完成并抓取设备端hilog日志文件后,是否自动清空设备端的日志文件,默认值为true。-->
        <clear></clear>                
        <!-- 设置用例执行完成后是否抓取设备端hilog日志文件,默认值为ON。注意设置为OFF时上述devicelog配置下的dir、loglevel以及clear属性不生效。 -->
        <enable>ON</enable>            
    </devicelog>
    <taskargs>
        <!-- pass_through,透传参数给测试用例。如{"task_id":"950191","user_define":{"execType":"3"}} -->
        <!-- 参数获取方法:from xdevice import Variables; print(Variables.config.pass_through) -->
        <pass_through></pass_through>
        <!-- repeat,用例重复运行多少次。大于1的整数才生效 -->
        <repeat></repeat>
        <!-- screenshot,操作类接口运行后是否截图。true开启/false不开启,默认值false -->
        <screenshot>false</screenshot>
        <!-- screenrecorder,用例Step步骤是否录屏。true开启/false不开启,默认值false -->
        <screenrecorder>false</screenrecorder>
    </taskargs>   
</user_config>

Hypium 测试用例由两部分组成:测试用例配置文件(JSON 格式)和测试用例脚本文件(Python 格式)。测试用例的组织方式支持两种模式:

  • 单个用例模式:包含一个测试用例脚本(Python)文件和一个测试用例配置(JSON)文件;
  • 测试套模式:包含一个测试套脚本(Python)文件、多个测试用例脚本(Python)文件和一个测试套配置(JSON)文件。

可根据实际需求选择合适的组织方式。

下面是我编写的一个测试时钟表盘切换的脚本:

收起
自动换行
深色代码主题
复制
#!/usr/bin/env python
# coding: utf-8

from devicetest.core.test_case import TestCase, Step
from hypium import *
from aw import Utils
import time


class FullScreenClockDialSwitchTest(TestCase):

    def __init__(self, controllers):
        self.TAG = self.__class__.__name__
        TestCase.__init__(self, self.TAG, controllers)
        self.driver = UiDriver(self.device1)

    def setup(self):
        Step('1. 回到桌面,确保初始环境干净')
        self.driver.swipe_to_home()
        time.sleep(1)

    def process(self):
        Step('2. 启动完美桌面时钟应用')
        self.driver.start_app('com.qm.myclock')
        time.sleep(2)

        Step('3. 校验首页是否正常显示')
        home_title = self.driver.find_element(BY.text('完美桌面时钟'))
        host.check_not_none(home_title)

        Step('4. 点击进入全屏时钟页面')
        full_screen_btn = self.driver.find_element(
            BY.id('btn_fullscreen_clock')  # 替换为真实ID
        )
        full_screen_btn.click()
        time.sleep(1)

        Step('5. 校验全屏时钟页面加载成功')
        full_screen_root = self.driver.find_element(
            BY.id('fullscreen_clock_root')
        )
        host.check_not_none(full_screen_root)

        Step('6. 打开时钟表盘切换面板')
        dial_switch_btn = self.driver.find_element(
            BY.id('btn_change_dial')
        )
        dial_switch_btn.click()
        time.sleep(1)

        Step('7. 获取所有可切换的时钟表盘')
        dial_items = self.driver.find_elements(
            BY.class_name('ClockDialItem')
        )
        host.check_greater(len(dial_items), 0)

        Step('8. 依次切换表盘,验证页面稳定性')
        for index, dial in enumerate(dial_items):
            Step(f'8.{index + 1} 切换到第 {index + 1} 个表盘')
            dial.click()
            time.sleep(1)

            # 校验全屏时钟页面仍然存在,未崩溃
            full_screen_root = self.driver.find_element(
                BY.id('fullscreen_clock_root')
            )
            host.check_not_none(full_screen_root)

        Step('9. 返回首页')
        self.driver.press_back()
        time.sleep(1)

        home_title = self.driver.find_element(BY.text('完美桌面时钟'))
        host.check_not_none(home_title)

    def teardown(self):
        Step('10. 停止完美桌面时钟应用')
        self.driver.stop_app('com.qm.myclock')

测试用例配置文件:

该文件主要描述测试用例的配置信息,如测试用例所需设备类型和数量、测试用例的测试驱动信息、测试用例的描述信息等。

收起
自动换行
深色代码主题
复制
{
    // description属性为测试用例的功能描述。
    "description": "Config for app test suites",
    // environment属性用于配置测试用例需要的设备类型和数量。
    "environment": [
        {
            "type": "device",   // 设备操作系统类型,device表示HarmonyOS设备。
            "label": "phone"    // 设备物理形态,phone为手机,tablet为平板,设置为空字符串或者移除该属性表示用例对设备类型无要求。用户可以通过执行hdc shell param get const.product.devicetype查看设备类型。
        }{
            "type": "device",   // 测试用例需要多个设备时,在environment属性中添加多个设备配置项。
            "label": "phone"
        }
    ],
    // driver字段主要描述测试用例的测试驱动是什么,以及具体要执行的Python脚本文件在哪(填写与当前JSON文件的相对路径即可)
    // 不填写则在当前JSON文件下寻找同名Python文件
    "driver": {
        "type": "DeviceTest",
           }
}

然后执行:打开命令行窗口,切换到测试脚本工程的根目录,执行以下命令可以进入Hypium控制台。

收起
自动换行
深色代码主题
复制
python -m hypium

Hypium 自动化执行过程中,不仅能完整复现真实用户操作路径,还能在执行结果中直接看到失败步骤对应的界面状态。

有一次测试中,自动化脚本稳定复现了一个此前“偶现”的问题:在快速切换样式并立即返回桌面时,组件刷新逻辑未完全结束,导致状态异常。

这个问题如果依赖人工测试,很难高频复现,而 Hypium 的价值正体现在这里——把“不稳定问题”变成“稳定复现”。

五、使用 DevEco Studio 本地测试:让问题在开发阶段就暴露

在引入云端测试和自动化测试之前,我首先把质量保障的第一道关口放在了 DevEco Studio 本地测试能力 上。

对于《完美桌面时钟》这样一款强调长期稳定运行、频繁界面刷新和多样式切换的应用来说,尽可能在开发阶段就发现问题,比后期修复要高效得多。

根据官方文档的推荐实践,我在本地主要使用了 单元测试、UI 测试以及 AppAnalyzer 体检测试 三类能力,对应用进行分层验证。

单元测试:确保时间与配置逻辑的正确性

《完美桌面时钟》的核心并不只是界面展示,背后涉及大量时间计算、样式配置解析以及状态同步逻辑。

例如:

不同时间格式的切换、24 小时制与 12 小时制处理、时钟样式参数的持久化存储等。

我通过 DevEco Studio 提供的单元测试能力,对这些纯逻辑模块进行了针对性验证。

代码本地单元测试有两种方式:

  • Instrument Test 测试用例存放在ohosTest测试目录下,需要运行在设备或模拟器上。Instrument Test支持ArkTS/JS语言

  • Local Test 测试用例存放在test测试目录下,不需要运行在设备或模拟器上。Local Test支持ArkTS语言,仅支持Stage模型,不支持测试C/C++方法及系统API

执行测试之后会生成测试报告:

有了测试报告可以快速确认修改是否影响到既有逻辑,避免“改了性能,却引入新 Bug”的情况发生。

在实际使用中,单元测试给出的失败信息定位清晰、可直接跳转到问题代码位置,大幅缩短了问题排查时间。

单元测试重点覆盖时间计算逻辑、样式配置数据解析等核心模块,确保在后续重构中不会引入功能回退。

Mock能力:使用Mock能力,对这些接口或对象进行模拟

当前Instrument Test和Local Test均支持对模块进行Mock,对于调用系统模块API或外部依赖模块,使用import mock,对于本地模块,使用hamock/hypium插件包的mock接口或者import mock。

黑盒覆盖率测试:DevEco Studio支持黑盒覆盖率测试,不需要开发测试用例,将编译插桩的HAP包推到设备上,然后对该应用/元服务模拟用户操作,测试完成后可生成覆盖率报告在解读

AppAnalyzer 体检测试:发现“暂时不出问题,但迟早出问题”的隐患

在本地测试中,对我帮助最大的是 AppAnalyzer 体检测试

DevEco Studio中使用:在工具栏的Tools的第一项

根据需要配置测试项和设备,真机可以:

点击开始按钮后开始测试:

通过体检测试,我快速发现了几个此前并未特别关注的问题:

例如部分页面存在冗余资源引用、个别生命周期方法中存在不必要的对象创建,以及某些逻辑在桌面常驻场景下可能带来的性能风险。

这些问题在短时间内并不会直接导致应用崩溃,但对于需要长期运行、频繁刷新的桌面时钟应用来说,却是非常典型的“隐性质量问题”。

体检测试给出的风险描述清晰明确,能够直接指导我进行针对性优化,而不是泛泛而谈。

AppAnalyzer 体检测试给我留下了非常深刻的印象。它直接指出了几个潜在风险点,例如个别页面存在冗余资源引用、某些生命周期回调中存在不必要的对象创建。这些问题虽然不会立刻导致崩溃,但长期运行在桌面场景下,极有可能放大为性能隐患。

通过本地测试提前修复这些问题,让后续线上测试的压力明显减轻。

六、使用云调试:解决兼容性“最后一公里”问题

在适配 HarmonyOS 不同设备形态的过程中,云调试成为我解决兼容性问题的重要工具。

我主要使用云调试来处理以下场景:

部分设备上桌面组件显示比例异常、特定分辨率下字体渲染不一致等问题。

通过云调试直接连接远程设备进行实时调试,可以在不具备实机的情况下,快速验证适配效果。这对独立开发者来说非常关键,大幅降低了设备成本和适配门槛。

云调试的入口在AGC首页(华为有赠送时长可以体验):

进入云调试页面有很多机型可以选择:

可以根据自己的需求选择设备调试:

开始调试后会生成测试报告,我们可以根据报告内容和日志内容分析APP的功能和运行情况。辅助我们进行开发调试。

七、使用云测试:在真实鸿蒙机型上验证“是否真的稳”

当本地和专项测试基本通过后,我将应用提交到云测试,选择了“上架测试 + 自定义测试”组合场景。

云测试最大的价值在于:

它不是模拟器,而是真实的鸿蒙设备矩阵。

在云测试报告中,我重点关注不同设备型号下的启动成功率、稳定性表现和异常日志。其中一台设备在长时间运行后出现了内存占用持续上升的情况,虽然未直接闪退,但已经具备风险信号。

根据云测试提供的日志信息,我最终定位到一个未及时释放的资源引用问题,并在后续版本中彻底修复。

云调试的入口在AGC的首页:

点击后进入云调试页面:

根据页面指引配置:

选择设备:

开始任务:

等待一段时间后,就可以查看结果了。

这次测试我的UI有一项测试没通过,我就可以根据报告指引去修改样式达到符合要求的目的。这样节省了很多时间,并且用户体验也好了很多。

八、使用 CI 集成:让质量检查成为“每一次提交的默认动作”

在《完美桌面时钟》的开发进入稳定迭代阶段后,我逐步将测试能力从“人工触发”升级为“流程自动触发”,在 CI(持续集成)工程中引入 HarmonyOS 官方测试工具,对应用质量进行持续守护。

所以这一阶段的目标非常明确:

只要代码发生变更,关键质量检查自动执行,问题不依赖人工发现。

我选择使用 Jenkins 作为 CI 工程工具,并在 Jenkins 节点中搭建 HarmonyOS 应用构建与测试环境。

选择 Jenkins 的主要原因有三点:

一是 Jenkins 对自定义脚本支持灵活,便于集成 DevEco Studio 相关命令;

二是 Jenkins 可以方便地接入自动化测试流程,适合执行 Hypium 测试用例;

三是 Jenkins 在个人开发和小团队中使用成本低,配置方式成熟,具备良好的可复制性。

整个 CI 流程的核心思路是:

一次代码提交,自动完成构建 + 测试 + 结果反馈

在 Jenkins 工程中,我配置了专门的 HarmonyOS 构建节点,节点环境中预先安装并配置了以下工具:

  • DevEco Studio(用于 HarmonyOS 应用构建与本地测试)

  • HarmonyOS SDK

  • Python 运行环境(用于执行 Hypium 自动化测试)

  • DevEco Testing Hypium 测试框架

Jenkins 通过 Pipeline 脚本统一调度这些工具,实现测试能力的自动化执行。

CI 集成带来的实际效果

在 CI 工程中引入 HarmonyOS 测试工具后,《完美桌面时钟》的质量保障方式发生了明显变化:

  • 测试不再依赖人工触发,而是成为每一次提交的必经流程

  • 问题更早暴露,大量缺陷在开发阶段就被拦截

  • 自动化测试帮助稳定复现人工测试中难以捕捉的偶现问题

这种实践方式,不仅提升了应用的稳定性,也显著降低了后期修复成本。

这一套 CI 集成方式在实际使用中具备良好的可复制性:

只需在现有 CI 工程中配置 HarmonyOS 构建环境,并引入 DevEco Studio 测试与 Hypium 自动化能力,即可快速搭建起完整的自动化质量守护体系。

对于个人开发者或小型团队来说,这种方式同样适用,能够在不显著增加人力成本的前提下,大幅提升应用质量。

九、使用 APMS:上线之后,依然持续守护品质

成功创建项目创建应用后,AGC将为应用自动开通APMS服务。

后续可按照以下步骤进入服务主界面,开始使用APMS服务。

  1. 登录AppGallery Connect,点击“开发与服务”。
  2. 在项目列表中找到您的项目,在项目下的应用列表中点击HarmonyOS NEXT应用/元服务。
  3. 在左侧导航栏选择“质量 > APMS > 异常管理/性能管理”,进入服务主界面,即可查看应用崩溃/应用指标等数据。

我的《完美桌面时钟》应用正式发布后,我通过 APMS 持续关注异常管理和性能管理数据。

APMS 帮助我第一时间捕获了少量线上崩溃问题,并提供了清晰的调用栈和设备信息,让问题定位不再依赖用户反馈。

同时,通过性能数据对比,我可以持续观察不同版本在启动耗时、稳定性等方面的变化趋势,确保优化是真正“向前”的。

十、回头看,这是一条很清晰的进阶路径

回顾整个过程,我为《完美桌面时钟》逐步建立起了一条清晰的质量闭环:

问题被发现 → 问题被量化 → 问题被修复 → 问题被提前拦截

这套流程在后续版本中也被完整保留下来,成为开发的一部分,而不是额外负担。

结语

从最初的“功能完成”,到现在的“体验稳定、性能可控、问题可追踪”,《完美桌面时钟》的品质提升并不是一次性的优化,而是一整套测试体系带来的改变。

HarmonyOS 提供的 DevEco Testing、Hypium、云测试、云调试、CI 集成以及 APMS,让我第一次真正建立起完整的质量闭环:

发现问题 → 定位问题 → 解决问题 → 预防问题。

这不仅让应用本身变得更可靠,也让我在开发过程中,对“好用”这件事有了更清晰、也更可落地的理解。

点赞
1
收藏
1
回复
分享
举报
浏览210 发布于2025-12-30 15:43辽宁
全部评论
最多点赞
最新发布
最早发布
写回答
新增插入模板功能
一键使用模板,快速填写内容,轻松发帖~
知道了
  • 为了保障您的信息安全,请勿上传您的敏感个人信息(如您的密码等信息)和您的敏感资产信息(如关键源代码、签名私钥、调试安装包、业务日志等信息),且您需自行承担由此产生的信息泄露等安全风险。
  • 如您发布的内容为转载内容,请注明内容来源。

我要发帖子

了解社区公约,与您携手共创和谐专业的开发者社区。