HarmonyOS回归测试开发实录
写Python脚本让手机自动操作App,同时采集性能数据,最后生成报告分析问题。搭建环境——安装DevEco Testing、Hypium、PyCharm,连接设备下载工程模板——拿到项目骨架编写原子用例——在models目录下,定义一个个具体的操作序列编写场景用例——在testcases目录下,把原子用例组合成完整的测试场景本地调试——在PyCharm里跑通脚本,确保没有语法和逻辑错误创建测试任
用DevEco Testing给你的App做个"体检"——场景化性能测试实战全记录
先聊聊,为什么需要性能测试
你有没有遇到过这种情况:自己写的App,功能都没问题,逻辑也没Bug,但是用起来就是觉得有点"卡"?点一下按钮要等一下,滑动列表的时候偶尔会掉帧,切换页面的时候感觉慢半拍。这些问题,用户不会给你报Bug,他们只会默默地把你的App卸了。
这就是性能问题。
性能测试这个事,说大不大,说小也不小。小的时候,你自己手动点点APP,感觉一下"好像还行"就行了;大了说,你要拿数据说话——这个页面的冷启动到底要多久?滑动的时候帧率是多少?CPU占用率是多少?内存有没有泄漏?这些数据不是你"感觉"能说清楚的,得用工具去量。
华为出了个东西叫 DevEco Testing,里面有一个功能叫"场景化性能测试"。今天咱们就来好好聊聊这个功能,从零开始,一步步带你把整个流程跑通。
先看看这个工具到底是个啥

DevEco Testing 是华为提供的一站式应用测试服务平台。你可以把它理解成一个"体检中心"——你的App是体检的人,DevEco Testing就是那个拿着各种仪器的医生。它帮你做稳定性测试、性能测试、基础质量测试等等。
而我们要用的"场景化性能测试",是其中专门针对性能的部分。它做的事情其实很好理解:
- 你写一段Python脚本,告诉它"请帮我模拟用户操作——打开设置,滑一滑,点一 点,再退出来"
- DevEco Testing 在手机上自动执行这些操作
- 在执行的过程中,它会自动采集各种性能数据——比如trace文件、视频录像、帧率数据等等
- 执行完以后,它会自动分析这些数据,给你生成一份完整的测试报告
整个过程你只需要写脚本和看报告,中间的那些脏活累活——采集数据、分析指标——框架都帮你干了。
这里还有个重要角色:DevEco Testing Hypium。这是华为出的一个基于Python的UI自动化测试框架,说白了就是我们写测试脚本用的工具包。你可以把它想象成一个"遥控器",你通过写Python代码来遥控手机上的各种操作——点击、滑动、输入文字、启动应用等等。
搭建环境:磨刀不误砍柴工
要干这件事,你得先把环境准备好。别急,我一项一项跟你说。
软件方面,你需要这几样东西
1. DevEco Testing
去华为开发者联盟下载最新版本就行。这是主程序,没有它什么都干不了。下载地址在华为开发者联盟的下载页面,搜索"DevEco Testing"就能找到。
2. DevEco Testing Hypium
这个也需要单独下载,也是在华为开发者联盟。注意版本要求,我们这次用到的一些接口是Hypium 6.0版本才有的,所以一定要下6.0.0以上的版本。
3. PyCharm
用来写和调试Python脚本的IDE。推荐用2022.3以后的社区版本,免费的就够用了。如果你平时就用别的Python IDE(比如VS Code),其实也行,只要能跑Python代码就行。
硬件方面
你需要一台跑HarmonyOS 5.0及以上系统的设备。可以是真机,也可以是模拟器,但建议用真机——因为性能测试嘛,真机的数据才靠谱。
环境配置
打开设备的"设置 > 系统 > 开发者选项",打开USB调试。然后用USB线把设备和电脑连起来。在命令行里跑一下:
hdc list targets
如果能看到设备的序列号,就说明连接成功了。然后在DevEco Testing里也要能识别到这台设备。

这里有个坑要注意:如果hdc list targets什么都返回不了,先检查一下USB线是不是数据线(有些线只能充电不能传数据),再检查一下驱动有没有装好。
拿到工程模板,先搞清楚结构

进入DevEco Testing的场景化性能测试界面,可以下载一个脚本工程模板。下载下来解压以后,你会看到这样的目录结构:
TestDemo/
config/ # 配置文件
user_config.xml
models/ # 原子用例(一个个小操作单元)
__init__.py
setting_interface_browsing.py
testcases/ # 场景用例(由原子用例组合而成)
OH_PerfDemoTest.py
OH_PerfDemoTest.json
main.py # 本地调试入口
我给你解释一下这个结构:
- config/:放配置文件的地方,主要是设备连接信息、日志级别这些。
- models/:放"原子用例"的。原子用例是最小的操作单元,比如"浏览设置界面"就是一个原子用例。它就像乐高积木里最小的一块,后面可以自由组合。
- testcases/:放"场景用例"的。场景用例是一个完整的测试场景,由一个或多个原子用例组成。比如"测试设置App的整体性能"就是一个场景用例。
- main.py:本地调试用的入口文件,双击运行就能在本地跑测试。
这里有个关键概念要搞明白,我觉得用"乐高积木"的比喻特别合适:
测试步骤是积木里最小的那个凸起——比如"点击WLAN按钮"就是一个步骤。
原子用例是一块完整的乐高积木——比如"浏览设置界面"包含了冷启动设置、上滑、下滑、点击WLAN、侧滑返回等好几个步骤。
场景用例是你用多块乐高积木拼出来的一个成品——比如"设置App性能测试"可能就由"浏览设置界面"、"切换WLAN"等多个原子用例拼成。
在实际开发中,一个场景用例可以包含1到N个原子用例,一个原子用例可以包含1到N个测试步骤。建议每个场景用例的步骤总数不要超过30个,太多了容易出异常,拆开来就好。
读懂main.py:测试的入口在哪
好,现在让我们看看代码。先从入口文件开始:
import time
from xdevice.__main__ import main_process
try:
pass_dict = dict()
pass_dict['task_id'] = time.strftime('%Y%m%d%H%M%S', time.localtime())
cmd = 'run -l OH_PerfDemoTest -ta pass_through:' + str(pass_dict)
main_process(cmd)
time.sleep(10)
except Exception as e:
print(e)
finally:
print("Task is End")
这段代码其实很简短,我逐行给你说说:
第一行import time,导入Python标准库的time模块,后面用来生成时间戳。
第二行from xdevice.__main__ import main_process,从Hypium框架里导入main_process函数。这是整个测试的"发动机"——它负责解析命令、找到用例、连接设备、执行测试,所有这些流程都是它来控制的。
然后进入try块:
pass_dict = dict()
pass_dict['task_id'] = time.strftime('%Y%m%d%H%M%S', time.localtime())
这里创建了一个字典,里面放了一个task_id,值是当前时间的格式化字符串,比如20260426143000,就是2026年4月26日14点30分00秒。这个task_id用来唯一标识这次测试任务,方便后面查找报告。
cmd = 'run -l OH_PerfDemoTest -ta pass_through:' + str(pass_dict)
这行构造了一个命令字符串。run是子命令,表示要运行测试;-l OH_PerfDemoTest指定了要运行的用例名称,这里的名字要和testcases目录下的文件名对应;-ta pass_through:后面跟的是要传给用例的参数。
main_process(cmd)
time.sleep(10)
main_process(cmd)就是正式开始执行测试了,把刚才构造的命令传进去。执行完后sleep 10秒,等一下让资源释放干净。
整个try-except-finally结构也很直观:如果执行过程中出了任何异常,就打印错误信息;不管成功还是失败,最后都打印一句"Task is End"表示流程结束。
这个文件你基本上不需要改什么,拿过来直接用就行。如果你以后要跑别的场景用例,只需要把-l后面的名字改成对应的用例名就好了。
读懂场景用例:OH_PerfDemoTest.py
接下来看场景用例文件,这是测试的核心部分:
import os
from hypium.advance.perf.application_model.perf_basecase import PerfBaseCase
from models.setting_interface_browsing import SettingInterfaceBrowering
class OH_PerfDemoTest(PerfBaseCase):
def __init__(self, controllers):
self.TAG = self.__class__.__name__
self.tests = [
"test_step"
]
self.case_id = os.path.splitext(os.path.basename(__file__))[0]
case_pkg = 'com.huawei.hmos.settings'
PerfBaseCase.__init__(self, controllers, case_pkg)
self.log.info("Case id is %s" % self.case_id)
def setup(self):
self.log.info("预置工作:初始化设备开始................." + self.devices[0].device_sn)
def test_step(self):
steps = [
SettingInterfaceBrowering(self.driver, self.case_id)
]
for item in steps:
item.execute()
def teardown(self):
result = self.get_case_result()
self.log.info("收尾工作................., result is {}".format(result))
PerfBaseCase.teardown(self)
我来一个方法一个方法地拆解。
__init__方法——初始化
def __init__(self, controllers):
self.TAG = self.__class__.__name__
self.__class__.__name__拿到的就是类名,也就是"OH_PerfDemoTest"。赋值给self.TAG是为了后面打日志的时候能快速定位是哪个用例输出的。
self.tests = [
"test_step"
]
这行指定了场景用例的执行入口。框架会去找这个名字对应的方法来执行。一个场景用例可以有多个入口方法,但通常一个就够了。
self.case_id = os.path.splitext(os.path.basename(__file__))[0]
这行代码做的事情是:拿到当前文件的文件名(不含扩展名)。__file__是Python内置变量,代表当前脚本的路径;os.path.basename()取最后一级文件名;os.path.splitext()把文件名和扩展名分开;[0]取文件名部分。所以最终self.case_id的值就是"OH_PerfDemoTest"。
这里有个重要的约定:文件名、类名、case_id 三者必须保持一致。如果不一致,框架可能找不到你的用例。
case_pkg = 'com.huawei.hmos.settings'
PerfBaseCase.__init__(self, controllers, case_pkg)
case_pkg是被测试应用的包名。这个包名用来做什么呢?它告诉框架在测试过程中要去采集这个应用的资源使用信息(CPU、内存等)。如果不配的话,框架就不会采集这些数据,那测试报告里就少了很多有价值的指标。
PerfBaseCase.__init__调用父类的初始化方法,把controllers(设备控制器)和case_pkg传进去。父类会做很多初始化工作——建立设备连接、初始化性能采集器等等。
setup方法——前置操作
def setup(self):
self.log.info("预置工作:初始化设备开始................." + self.devices[0].device_sn)
setup方法在测试执行之前自动调用,用来做一些准备工作。这里只是打了一行日志,记录一下设备的序列号。在实际项目中,你可能需要在这里做一些更复杂的操作,比如清空应用缓存、重置设备状态等等。
test_step方法——核心测试逻辑
def test_step(self):
steps = [
SettingInterfaceBrowering(self.driver, self.case_id)
]
for item in steps:
item.execute()
这是整个场景用例最核心的方法。它做的事情很简单:
- 创建一个列表
steps,里面放的是要执行的原子用例。这里只有一个原子用例SettingInterfaceBrowering,传入self.driver(设备驱动器)和self.case_id(用例ID)。 - 用一个for循环,按顺序执行每个原子用例的
execute()方法。
如果你的场景需要执行多个原子用例,直接往这个列表里加就行:
steps = [
SettingInterfaceBrowering(self.driver, self.case_id),
SomeOtherModel(self.driver, self.case_id),
YetAnotherModel(self.driver, self.case_id),
]
teardown方法——收尾操作
def teardown(self):
result = self.get_case_result()
self.log.info("收尾工作................., result is {}".format(result))
PerfBaseCase.teardown(self)
teardown在测试执行完成后自动调用。self.get_case_result()获取测试结果,然后打印出来。最后调用父类的teardown方法,让框架做一些收尾工作——比如关闭性能采集器、释放资源等等。
别忘了JSON配置文件
和OH_PerfDemoTest.py同目录下还有一个OH_PerfDemoTest.json文件:
{
"description": "Config for OpenHarmony devicetest test cases",
"environment": [
{
"type": "device"
}
],
"driver": {
"type": "DeviceTest",
"py_file": ["OH_PerfDemoTest.py"]
}
}
这个JSON文件是每个场景用例必须配的。它告诉框架三件事:
environment:测试环境类型,这里是device,表示需要在真实设备上运行。driver:驱动配置,type是DeviceTest,py_file指定了场景用例的Python文件。description:描述信息,随便写什么都行。
注意一点:每个场景用例都需要一个同名的JSON配置文件。如果你新建了一个叫MyNewTest.py的场景用例,就要在同一个目录下创建一个MyNewTest.json。
读懂原子用例:真正干活的地方
现在来看真正干活的部分——原子用例。我们的示例中只有一个原子用例setting_interface_browsing.py,它模拟的是"用户浏览设置界面"这个操作。
先看完整的代码,我会在后面逐步解释:
from hypium import BY
from hypium.advance.perf.application_model.model_base import ModelBase
from hypium.advance.perf.driver_perf.idriver_perf import IDriverPerf
from hypium.advance.perf.driver_perf.tag import SceneType
from hypium.model import UiParam
'''
@原子用例
设置界面浏览
@预置条件
无
@用例步骤
1.冷启动设置
2.上滑1次浏览界面
3.下滑1次浏览界面
4.点击WLAN
5.侧滑返回
6.再次点击WLAN,等待1秒
7.侧滑返回
8.点击显示和亮度
9.侧滑返回
10.上滑返回桌面
'''
APP_NAME = "设置"
class SettingInterfaceBrowering(ModelBase):
def __init__(self, uidriver: IDriverPerf, case_id):
ModelBase.__init__(self, uidriver, case_id)
self.scene_no = "setting_interface_browsing"
self.scene_name = "设置界面浏览"
self.scene_type = "系统设置场景"
self.scene_path = "日常高频操作-基础操作场景-系统通用操作场景-系统设置场景"
self.driver = uidriver
def setup(self):
self.driver.stop_app('com.huawei.hmos.settings')
self.driver.go_home()
@ModelBase.scene_recover
def execute(self):
# 1.冷启动应用'设置'
self.driver.start_application_perf("设置", SceneType.COLD_START)
self.driver.wait(1)
# 2.上滑1次浏览界面
self.driver.swipe_perf(UiParam.UP,
tag=self.create_tag("上滑1次浏览界面", SceneType.NO_PAGE_SWITCH))
# 3.下滑1次浏览界面
self.driver.swipe_perf(UiParam.DOWN,
tag=self.create_tag("下滑1次浏览界面", SceneType.NO_PAGE_SWITCH))
# 4.点击WLAN
com = self.driver.find_component(BY.text("WLAN"))
self.driver.touch_perf(com, tag=self.create_tag("点击WLAN", SceneType.WITH_PAGE_SWITCH))
# 5.侧滑返回
self.driver.swipe_to_back_perf(tag=self.create_tag("侧滑返回", SceneType.WITH_PAGE_SWITCH))
# 6.再次点击WLAN
coms = self.driver.find_all_components(BY.text('WLAN'))
self.driver.touch_perf(coms[0], tag=self.create_tag("再次点击WLAN", SceneType.WITH_PAGE_SWITCH))
# 7.侧滑返回
self.driver.swipe_to_back_perf(tag=self.create_tag("侧滑返回", SceneType.WITH_PAGE_SWITCH))
# 8.点击显示和亮度
self.driver.touch_perf(BY.text('显示和亮度'),
tag=self.create_tag("点击显示和亮度", SceneType.WITH_PAGE_SWITCH))
# 9.侧滑返回
self.driver.swipe_to_back_perf(tag=self.create_tag("侧滑返回", SceneType.WITH_PAGE_SWITCH))
# 10.上滑返回桌面
self.driver.swipe_to_home_perf(tag=self.create_tag("上滑返回桌面", SceneType.WITH_PAGE_SWITCH))
def teardown(self):
self.driver.stop_app('com.huawei.hmos.settings')
导入部分
from hypium import BY
from hypium.advance.perf.application_model.model_base import ModelBase
from hypium.advance.perf.driver_perf.idriver_perf import IDriverPerf
from hypium.advance.perf.driver_perf.tag import SceneType
from hypium.model import UiParam
BY:用来定位UI控件的工具,比如通过文字、ID等条件来找控件。ModelBase:原子用例的基类,所有原子用例都要继承它。IDriverPerf:性能驱动接口的类型声明,用于类型提示。SceneType:场景类型枚举,用来标记操作是否涉及页面切换。UiParam:UI参数类,定义了滑动方向等常量。
顶部的注释块
'''
@原子用例
设置界面浏览
@预置条件
无
@用例步骤
1.冷启动设置
2.上滑1次浏览界面
3.下滑1次浏览界面
4.点击WLAN
5.侧滑返回
6.再次点击WLAN,等待1秒
7.侧滑返回
8.点击显示和亮度
9.侧滑返回
10.上滑返回桌面
'''
这段注释不是装饰性的,它是原子用例的"设计文档"。写的时候要尽量把每个步骤都列清楚——以后回过头来看代码,一看注释就知道这个用例在干什么,不需要一行行代码去猜。
__init__方法
def __init__(self, uidriver: IDriverPerf, case_id):
ModelBase.__init__(self, uidriver, case_id)
self.scene_no = "setting_interface_browsing"
self.scene_name = "设置界面浏览"
self.scene_type = "系统设置场景"
self.scene_path = "日常高频操作-基础操作场景-系统通用操作场景-系统设置场景"
self.driver = uidriver
调用父类ModelBase的初始化方法,然后设置几个属性:
scene_no:原子用例的唯一编号,一般用文件名(去掉.py)就行。scene_name:原子用例的中文名称,会显示在报告里。scene_type:原子用例的类型分类,方便管理。scene_path:原子用例所属的路径层级,体现了操作的分类体系。
setup方法——原子用例的预处理
def setup(self):
self.driver.stop_app('com.huawei.hmos.settings')
self.driver.go_home()
在原子用例执行之前,先做两件事:
stop_app:杀掉设置App的进程。这一步很重要——因为我们要测的是"冷启动"性能,如果设置App已经在后台跑着了,那启动速度就不是冷启动了,测试数据就不准。go_home:回到手机桌面。确保每次测试都从同一个起点开始。
execute方法——核心操作步骤
这个方法上面有一个装饰器@ModelBase.scene_recover,这个装饰器的作用是:如果执行过程中出了异常(比如找不到某个控件),框架会自动尝试恢复场景,而不是直接崩溃。在实际测试中,设备的状态有时候不太稳定,这个装饰器能大大提高测试的鲁棒性。
步骤1:冷启动设置App
self.driver.start_application_perf("设置", SceneType.COLD_START)
start_application_perf是启动应用的性能测试专用接口。第一个参数是应用名称(就是桌面上显示的那个名字),框架会从桌面开始滑动查找这个App并启动。第二个参数SceneType.COLD_START标记这是一个冷启动操作——框架会在启动前后分别采集性能数据,从而计算出冷启动耗时。
这里有个重要的注意事项:这个接口是Hypium 6.0版本才新增的,如果你用的是老版本会报错。一定要确认你的Hypium版本是6.0.0以上。
self.driver.wait(1)
等1秒钟,让设置App的界面完全加载稳定,再进行下一步操作。如果界面还没稳定就开始滑动或点击,一方面可能找不到控件导致报错,另一方面采集到的数据也不准确——因为你测的不只是"操作本身"的性能,还包含了"界面没加载完"的影响。
步骤2和3:上下滑动浏览界面
self.driver.swipe_perf(UiParam.UP,
tag=self.create_tag("上滑1次浏览界面", SceneType.NO_PAGE_SWITCH))
self.driver.swipe_perf(UiParam.DOWN,
tag=self.create_tag("下滑1次浏览界面", SceneType.NO_PAGE_SWITCH))
swipe_perf是滑动的性能测试接口。UiParam.UP表示向上滑,UiParam.DOWN表示向下滑。
每一步操作后面的tag参数很关键。self.create_tag("描述", SceneType.xxx)会创建一个标签,框架用这个标签来标记这一步的性能数据。SceneType.NO_PAGE_SWITCH表示这个滑动操作不会触发页面切换(只是在同一个页面上滑动浏览),SceneType.WITH_PAGE_SWITCH表示会切换到新页面。框架根据这个标记来决定性能数据的分析方式。
步骤4:点击WLAN
com = self.driver.find_component(BY.text("WLAN"))
self.driver.touch_perf(com, tag=self.create_tag("点击WLAN", SceneType.WITH_PAGE_SWITCH))
这里分两步走:先用find_component找到界面上文字为"WLAN"的控件,然后用touch_perf点击它。
BY.text("WLAN")表示"找文字内容为WLAN的控件"。find_component返回一个UiComponent对象,然后touch_perf可以直接接收这个对象,会自动获取控件坐标并执行点击。
为什么这一步标记为WITH_PAGE_SWITCH呢?因为点击WLAN以后会进入WLAN设置页面,这是一个新的页面,所以标记为页面切换。
步骤5:侧滑返回
self.driver.swipe_to_back_perf(tag=self.create_tag("侧滑返回", SceneType.WITH_PAGE_SWITCH))
swipe_to_back_perf是专门用来执行"从屏幕右侧滑动返回"操作的接口。在HarmonyOS里,从屏幕右边缘向左滑是标准的返回手势,这个接口就是模拟这个操作。
步骤6:再次点击WLAN
coms = self.driver.find_all_components(BY.text('WLAN'))
self.driver.touch_perf(coms[0], tag=self.create_tag("再次点击WLAN", SceneType.WITH_PAGE_SWITCH))
注意这里和步骤4的区别:步骤4用的是find_component(找第一个匹配的),步骤6用的是find_all_components(找所有匹配的),然后通过coms[0]取第一个。
为什么同一个操作要用两种不同的写法呢?其实这两种方式都能实现同样的效果,这里只是展示给你看两种API的用法。在实际项目中,你用哪种都行,看个人习惯。
步骤7到10:重复返回和导航
# 7.侧滑返回
self.driver.swipe_to_back_perf(tag=self.create_tag("侧滑返回", SceneType.WITH_PAGE_SWITCH))
# 8.点击显示和亮度
self.driver.touch_perf(BY.text('显示和亮度'),
tag=self.create_tag("点击显示和亮度", SceneType.WITH_PAGE_SWITCH))
# 9.侧滑返回
self.driver.swipe_to_back_perf(tag=self.create_tag("侧滑返回", SceneType.WITH_PAGE_SWITCH))
# 10.上滑返回桌面
self.driver.swipe_to_home_perf(tag=self.create_tag("上滑返回桌面", SceneType.WITH_PAGE_SWITCH))
步骤8有一个值得注意的地方:touch_perf不仅可以接收UiComponent对象,还可以直接接收BY条件。当传入BY条件时,框架会自动先查找控件,再执行点击。所以self.driver.touch_perf(BY.text('显示和亮度'), ...)和先find_component再touch_perf是等价的,只是写法更简洁。
步骤10的swipe_to_home_perf从屏幕底部上滑返回桌面,这是HarmonyOS的手势导航操作。
teardown方法——清理收尾
def teardown(self):
self.driver.stop_app('com.huawei.hmos.settings')
测试结束后杀掉设置App的进程,保持设备环境干净。这样即使你连续跑多个原子用例,也不会互相影响。
配置文件解读
最后看一下config/user_config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<user_config>
<environment>
<device type="usb-hdc">
<sn></sn>
</device>
</environment>
<testcases>
<dir></dir>
</testcases>
<loglevel>INFO</loglevel>
<devicelog>ON</devicelog>
</user_config>
这个配置文件的结构很清晰:
environment:定义测试环境。type="usb-hdc"表示通过USB连接设备,<sn>是设备序列号(留空表示自动识别)。testcases:指定测试用例目录。<dir>留空表示使用默认目录。loglevel:日志级别,设为INFO表示输出一般信息。如果调试的时候想看更详细的信息,可以改成DEBUG。devicelog:设为ON表示采集设备日志。在性能测试中建议保持开启,方便出问题时排查。
在DevEco Testing上跑测试
脚本写好了,本地也调试通过了,就可以在DevEco Testing上正式跑测试了。

打开DevEco Testing客户端,找到"专项测试"菜单,点击"场景化性能测试"。然后:
- 选择测试设备——就是你连着的那台手机
- 选择执行轮数——可以设1到10轮。设多轮的话,每个用例会重复执行那么多次,报告里会展示每轮的数据和多轮的均值。如果你想做稳定性评估,建议设3轮以上。
- 选择场景用例路径——指向你testcases目录所在的位置

任务创建好以后,它会自动开始执行。执行过程中,页面上会实时显示当前执行到哪个步骤了,以及执行日志。你只需要耐心等着就行。
看懂测试报告
测试跑完了,会自动生成一份测试报告。这份报告是整个流程最有价值的输出,你得学会看。

报告包含以下内容:
- 任务信息:设备信息、执行时间、执行轮数等基本信息
- 执行日志:完整的执行过程日志,可以回溯每一步发生了什么
- 整体评估:所有用例的执行结果汇总,一眼就能看出哪些通过了、哪些有问题
- 用例详情:每个用例每一轮的详细数据,点进去可以看到步骤级别的指标
- 指标监控数据:CPU、内存、帧率、功耗等各种性能指标的具体数值
- 资源文件:每个步骤对应的trace文件和视频录像

看报告的时候,我建议你重点关注这几件事:
- 帧率(FPS):滑动操作时帧率是多少?有没有低于60fps的情况?如果出现了掉帧,说明页面的渲染性能有问题。
- 响应时间:点击某个按钮后,页面切换花了多长时间?如果响应时间太长,用户体验就会很差。
- 内存占用:App运行过程中内存有没有持续增长?如果一直涨不回落,很可能存在内存泄漏。
- CPU占用率:在操作过程中CPU占用是多少?如果某个操作CPU占用特别高,说明可能存在性能瓶颈。
深入分析:用DevEco Profiler看trace文件

如果你在报告里发现某些指标异常,想进一步定位原因,就可以去看trace文件。
测试过程中采集的trace文件是一种性能追踪数据,它记录了每个时间点系统的各种状态。你可以用 DevEco Studio 6.0.1.260 及以上版本中自带的 DevEco Profiler 工具来打开和查看这些文件。
另外,如果你没有装DevEco Studio,也可以把perfdata文件用压缩软件(比如7-Zip)解压,里面的trace文件可以用华为的 smartperf 网站在线查看。
trace文件里能看到什么?比如:
- 函数调用的时间线,哪些函数执行时间长一目了然
- 各线程的CPU调度情况
- 内存分配和释放的时间点
- 图形渲染管线的执行情况
通过分析这些信息,你就能精确定位性能瓶颈到底在哪个函数、哪一行代码。
最后总结一下整个流程
回顾一下,我们今天做的事情,可以用一句话概括:写Python脚本让手机自动操作App,同时采集性能数据,最后生成报告分析问题。
具体步骤是:
- 搭建环境——安装DevEco Testing、Hypium、PyCharm,连接设备
- 下载工程模板——拿到项目骨架
- 编写原子用例——在models目录下,定义一个个具体的操作序列
- 编写场景用例——在testcases目录下,把原子用例组合成完整的测试场景
- 本地调试——在PyCharm里跑通脚本,确保没有语法和逻辑错误
- 创建测试任务——在DevEco Testing中配置并启动测试
- 查看测试报告——分析性能指标,定位问题
- 深入分析——用DevEco Profiler打开trace文件,找到根因
整个过程听起来步骤不少,但当你跑过一次之后就会发现,核心的工作其实就两块:写好测试脚本和看懂测试报告。其他的都是配置和流程性的操作。
场景化性能测试最大的价值在于可量化和可重复。你不再是"感觉这个页面有点慢",而是能拿出具体的数据——“冷启动耗时2.3秒,比上一版本增加了0.5秒;滑动帧率平均55fps,低于60fps的目标值”。有了数据,你才能有针对性地优化,优化完了再跑一遍测试验证效果。这就是性能测试的意义。
更多推荐

所有评论(0)