23. 功耗自动化测试:编写功耗测试脚本、自动化压测场景、功耗回归测试

功耗优化做得好不好,不能光靠嘴说。你得有数据,有对比,有回归。

我见过太多团队,优化了一版功耗,下个版本又改回去了。为什么?因为没有自动化测试来守住底线。说白了,功耗优化和功能开发一样,需要持续集成,需要回归守护。

为什么需要自动化功耗测试?

手动测功耗,一次两次还行。但你要做回归,每天跑几十个场景,手都点废了。而且人测有个大问题——操作时机不准。你想想看,多按了0.5秒,电流波形就变了,数据根本没法对比。

自动化测试能解决三个核心问题:

  • 一致性:每次操作的时间点、间隔、顺序完全一致
  • 覆盖率:可以同时覆盖几十个场景,人做不到
  • 可追溯:每次跑完都有日志和波形,出了问题能定位

核心观点:功耗自动化测试不是为了替代手动测试,而是为了守住回归底线。让机器做重复的事,让人做分析的事。

编写功耗测试脚本

写脚本这事,我习惯用Python。为什么?生态好,仪器驱动多,上手快。下面是我常用的脚本框架:

import subprocess
import time
import csv
from power_monitor import PowerMonitor

class CameraPowerTest:
    def __init__(self, device_serial, monitor_ip):
        self.device = device_serial
        self.monitor = PowerMonitor(monitor_ip)
        self.results = []
    
    def setup(self):
        """预热设备,确保状态一致"""
        subprocess.run(f"adb -s {self.device} shell am force-stop com.android.camera2")
        time.sleep(2)
        # 关闭后台无关进程
        subprocess.run(f"adb -s {self.device} shell pm disable com.example.bloatware")
    
    def test_preview(self, duration=30):
        """测试预览功耗"""
        self.monitor.start_recording()
        subprocess.run(f"adb -s {self.device} shell am start -a android.media.action.IMAGE_CAPTURE")
        time.sleep(2)  # 等待预览稳定
        time.sleep(duration)
        avg_current = self.monitor.stop_recording()
        self.results.append({
            'scene': 'preview',
            'avg_current_ma': avg_current,
            'duration_s': duration
        })
    
    def test_video_recording(self, duration=60):
        """测试录像功耗"""
        self.monitor.start_recording()
        # 模拟点击录像按钮
        subprocess.run(f"adb -s {self.device} shell input tap 540 1800")
        time.sleep(duration)
        subprocess.run(f"adb -s {self.device} shell input tap 540 1800")
        avg_current = self.monitor.stop_recording()
        self.results.append({
            'scene': 'video_recording',
            'avg_current_ma': avg_current,
            'duration_s': duration
        })
    
    def run_all(self):
        self.setup()
        self.test_preview()
        self.test_video_recording()
        self.save_report()
    
    def save_report(self):
        with open('power_report.csv', 'w') as f:
            writer = csv.DictWriter(f, fieldnames=['scene', 'avg_current_ma', 'duration_s'])
            writer.writeheader()
            writer.writerows(self.results)

if __name__ == '__main__':
    tester = CameraPowerTest('ABCD1234', '192.168.1.100')
    tester.run_all()

小技巧:脚本里我习惯加一个warmup()方法。因为刚开机时,电流往往偏高,等30秒再测,数据更稳定。这个坑我踩过,第一次测出来的数据比实际高了20%。

自动化压测场景设计

压测不是乱测。你得知道相机最耗电的场景是什么。我个人经验,以下场景必须覆盖:

场景 操作序列 预期时长 关注指标
连续预览 打开相机 → 保持预览30分钟 30min 平均电流、温升
反复拍照 拍照 → 等待2s → 拍照,循环100次 约5min 峰值电流、恢复时间
录像循环 开始录像 → 5min → 停止 → 等待3s,循环10次 约50min 平均电流、温度
模式切换 拍照→录像→夜景→人像,循环50次 约10min 切换电流尖峰
低电量场景 电量5%时打开相机并录像 10min 是否降频、电流波动

为什么要设计这些场景?我举个例子。有一次我们做功耗优化,预览功耗降了15%,结果一跑反复拍照场景,发现每次拍照后电流恢复时间变长了。原来是为了省电,把ISP的时钟降得太低,导致拍照后重新拉起很慢。这个场景如果不压测,根本发现不了。

功耗回归测试流程

回归测试,说白了就是每次代码提交后,自动跑一遍功耗基线。我建议这样搭:

# 回归测试脚本示例
#!/bin/bash
# 参数:$1 = 基线版本号,$2 = 当前版本号

BASELINE=$1
CURRENT=$2

# 1. 刷入基线版本
fastboot flash system baseline_${BASELINE}.img
adb reboot
sleep 30

# 2. 跑基线功耗
python3 camera_power_test.py --output baseline.csv

# 3. 刷入当前版本
fastboot flash system current_${CURRENT}.img
adb reboot
sleep 30

# 4. 跑当前功耗
python3 camera_power_test.py --output current.csv

# 5. 对比结果
python3 compare_power.py --baseline baseline.csv --current current.csv

# 6. 如果功耗增加超过5%,报警
if [ $? -gt 5 ]; then
    echo "功耗回归失败!当前版本功耗增加超过5%"
    exit 1
fi

注意:回归测试的环境必须一致。我曾经吃过亏——白天跑和晚上跑,室温差了5度,电流数据差了10%。后来我规定:回归测试必须在恒温箱里跑,温度控制在25±1°C。

数据对比与阈值设定

拿到数据后,怎么判断有没有回归?我一般设三个阈值:

  • 绿色:功耗变化在±3%以内,正常波动
  • 黄色:功耗增加3%~8%,需要人工确认
  • 红色:功耗增加超过8%,直接阻断合入

阈值怎么定?我建议先跑10次基线,算标准差。比如预览场景平均电流是500mA,标准差是10mA,那±3%就是±15mA。超过这个范围,说明有显著变化。

SVG:功耗自动化测试流程

功耗自动化测试流程 1. 编写测试脚本 Python + ADB + 仪器驱动 2. 设计压测场景 预览/拍照/录像/切换 3. 执行自动化测试 恒温环境 + 基线对比 4. 数据采集与清洗 去噪、平滑、截取稳定段 5. 对比基线分析 计算偏差、判断回归 6. 决策与反馈 通过/告警/阻断合入 ✅ 通过(≤3%) 自动合入 ⚠️ 告警(3%~8%) 人工确认 ❌ 阻断(>8%) 退回修改 环境要求:恒温25°C ± 1°C | 基线版本:最近稳定版 | 仪器:精度±0.1mA

避坑指南

做功耗自动化测试,有几个坑我踩过,分享给你:

  • 仪器漂移:电流计用久了会漂。我习惯每个月校准一次,用标准电阻验证。
  • USB供电干扰:adb连着的USB线会供电,影响电流测量。解决方案是用无线adb,或者用USB隔离器。
  • 后台进程干扰:测试前一定要确保没有后台更新、同步在跑。我脚本里会先跑一个dumpsys batterystats --reset
  • 温度累积:连续跑压测,手机会越来越热。我建议每个场景之间休息2分钟,让温度降下来。

总结一下:功耗自动化测试不是一锤子买卖。它需要持续维护脚本、更新场景、校准仪器。但一旦跑起来,它能帮你守住功耗底线,避免「优化一时爽,回归火葬场」的尴尬。

公众号:蓝海资料掘金营,微信deep3321