27. 启动优化自动化测试:UI Automator模拟启动、重复性测试、性能基线
启动优化做完了,效果到底怎么样?
说实话,光靠手动点几下、肉眼看看,根本不够。我见过太多团队,优化完自我感觉良好,结果一上自动化测试,数据波动大得吓人。所以今天咱们聊聊,怎么用UI Automator把启动测试做成自动化,跑出靠谱的性能基线。
为什么需要自动化测试?
你想想看,手动测试有几个硬伤:
- 手速不一致:每次点击的间隔、力度都不一样,数据没法对比
- 样本量太少:手动跑个三五次就累了,但启动时间本身就有随机波动
- 回归成本高:改一行代码,就得把所有机型重新测一遍,谁受得了?
我在项目中遇到过,有一次优化了冷启动,手动测了5次,平均快了200ms。结果自动化一跑,50次下来,发现只是运气好,实际只快了50ms。嗯,从那以后,我再也不信手动数据了。
核心原则:启动优化测试,必须自动化、重复化、基线化。缺一不可。
UI Automator 模拟启动
UI Automator 是 Android 官方提供的 UI 测试框架。用它模拟启动,说白了就是写个脚本,让手机自动打开应用、等待首页加载、记录时间。
我习惯用这种方式来写启动测试:
// 冷启动测试示例
public class LaunchTest extends BaseTest {
@Test
public void testColdLaunch() {
// 1. 先杀掉进程,保证是冷启动
UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
device.executeShellCommand("am force-stop com.example.app");
// 2. 等待进程彻底消失
SystemClock.sleep(2000);
// 3. 记录开始时间
long startTime = System.currentTimeMillis();
// 4. 启动应用
Context context = InstrumentationRegistry.getContext();
Intent intent = context.getPackageManager()
.getLaunchIntentForPackage("com.example.app");
context.startActivity(intent);
// 5. 等待首页关键元素出现
UiObject2 homeElement = device.wait(
Until.findObject(By.res("com.example.app:id/home_container")),
5000);
// 6. 记录结束时间
long endTime = System.currentTimeMillis();
// 7. 计算启动耗时
long launchTime = endTime - startTime;
System.out.println("冷启动耗时: " + launchTime + "ms");
// 8. 断言:不能超过性能基线
assertTrue("启动时间超标: " + launchTime + "ms", launchTime < 2000);
}
}
小技巧:判断首页加载完成,别用「等几秒」这种笨办法。应该等一个关键UI元素出现,比如首页的列表、标题栏。这样更准确,也更能反映真实用户体验。
重复性测试:跑出稳定数据
单次测试没有意义。启动时间受很多因素影响:CPU频率、内存状态、后台进程……所以必须重复跑,取统计值。
我个人习惯的做法是:
- 冷启动跑20次:每次都要杀掉进程,模拟首次打开
- 温启动跑10次:按Home键再回来,模拟切换场景
- 热启动跑10次:按最近任务键再切回来
跑完之后,我一般看这几个指标:
| 指标 | 说明 | 我常用的阈值 |
|---|---|---|
| P50(中位数) | 去掉极端值后的典型表现 | 冷启动 < 1.5s |
| P95 | 最差情况下的表现 | 冷启动 < 2.5s |
| 标准差 | 数据波动程度 | < 200ms |
为什么要看P95?因为用户遇到的就是最差情况。平均值再好看,偶尔卡一次,用户就骂娘了。
注意:测试前一定要保证手机状态一致。比如:关闭自动亮度、关闭省电模式、清空后台进程。我曾经因为没关省电模式,数据直接翻了一倍,排查了半天才发现。
性能基线:让数据说话
基线是什么?说白了就是一条红线。每次代码提交后,自动化测试跑出来的数据,不能越过这条线。
我建议这样建立基线:
- 先跑一轮基准测试:在稳定版本上,跑50次冷启动,记录P50和P95
- 写入配置文件:把基线值写到项目的性能配置里
- CI/CD集成:每次构建自动跑测试,超基线就报警
// 性能基线配置示例
public class PerformanceBaseline {
// 冷启动基线(单位:ms)
public static final long COLD_LAUNCH_P50 = 1500;
public static final long COLD_LAUNCH_P95 = 2500;
// 温启动基线
public static final long WARM_LAUNCH_P50 = 800;
public static final long WARM_LAUNCH_P95 = 1200;
}
有了基线,你就能回答老板的灵魂拷问:「这次优化到底有没有效果?」直接把数据甩过去,比说一万句都有用。
自动化测试的整体流程
我把整个流程画了张图,方便你理解:
避坑指南
做自动化测试,有几个坑我踩过,分享给你:
- 不要用Thread.sleep()等固定时间:不同机型速度不同,应该用UI Automator的wait()方法,等元素出现
- 注意第一次启动的特殊性:安装后的第一次启动,可能会有dex优化、资源加载,数据要单独记录
- 别忘了清理缓存:每次测试前,最好清一下应用缓存,避免上次的数据影响本次结果
我的习惯:每次跑完测试,自动把结果发到钉钉/飞书群。这样团队每个人都能看到性能趋势,谁改坏了代码,一目了然。
好了,自动化测试这块就聊到这儿。记住一句话:没有数据支撑的优化,都是耍流氓。把UI Automator用起来,让机器替你盯着性能,你就能腾出手来做更有价值的事。