专项测试自动化-如何自动化获取APP的FPS、丢帧率等信息来测试流畅度(基于Android,Java)

  • 开始之前

这里只说明我自己获取FPS、丢帧率等信息来测试流畅度的自动化代码,具体的业务技术知识和手工测试的方法可参考另两篇博客:
  • 专项测试-流畅度测试之前的知识储备-Andorid中VSync机制的介绍
  • 专项测试-如何测试APP流畅度,基于adb shell dumpsys gfxinfo命令来获取fps和丢帧率
话不多说,进入正题~
  • 主要思路

当渲染时间大于16.67,按照垂直同步机制,该帧就已经渲染超时,那么,如果它正好是16.67的整数倍,比如66.68,则它花费了4个垂直同步脉冲,减去本身需要一个,则超时3个;如果它不是16.67的整数倍,比如67,那么它花费的垂直同步脉冲应向上取整,即5个,减去本身需要一个,即超时4个,可直接算向下取整

最后的计算方法思路:
执行一次命令,总共收集到了m帧(理想情况下m=128),但是这m帧里面有些帧渲染超过了16.67毫秒,算一次jank,一旦jank,
需要用掉额外的垂直同步脉冲。其他的就算没有超过16.67,也按一个脉冲时间来算(理想情况下,一个脉冲就可以渲染完一帧)

所以FPS的算法可以变为:
m / (m + 额外的垂直同步脉冲) * 60

  • 实现代码和注释

package getResource;

import commons.Commons;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;

public class GetFps {

    //清空之前采样的数据,防止统计重复的时间
    private static String clearCommand = "adb shell dumpsys SurfaceFlinger --latency-clear";
    private static long jumpingFrames = 0; //jank次数,跳帧数
    private static long totalFrames = 0;  //统计的总帧数
    private static float lostFrameRate = 0; //丢帧率
    private static float fps; //fps值

    public static float[] getInfo(String deviceName, String packageName){
        String gfxCMD = "adb -s " + deviceName + " shell dumpsys gfxinfo " + packageName;
        float[] info = new float[2];
        int vsyncOverTimes = 0; // 垂直同步次数
        try {
            Runtime.getRuntime().exec(clearCommand);
            Process process = Runtime.getRuntime().exec(gfxCMD);
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line; boolean flag = false;
            while ((line = reader.readLine()) != null){
                if (line.length() > 0){
                    if (line.contains("Execute")){
                        flag = true;
                        continue;
                    }
                    if (line.contains("View hierarchy")){
                        break;
                    }
                    if (flag){
                        String[] times = line.trim().split("\\s+");
                        //计算一帧所花费的时间
                        float onceTime = Float.parseFloat(times[0]) + Float.parseFloat(times[1]) + Float.parseFloat(times[2]) + Float.parseFloat(times[3]);
                        totalFrames += 1; //统计总帧数
                        if (onceTime > 16.67){//以Android定义的60FPS为标准
                            jumpingFrames += 1; // 统计跳帧jank数
                            //统计额外花费垂直同步脉冲的数量
                            if (onceTime % 16.67 == 0){
                                vsyncOverTimes += onceTime / 16.67 - 1;
                            }else {
                                vsyncOverTimes += Math.floor(onceTime / 16.67); //向下取整即可
                            }
                        }
                    }
                }
            }
            if (totalFrames > 0){
                fps = totalFrames / (totalFrames + vsyncOverTimes) * 60;
                lostFrameRate = jumpingFrames / totalFrames;
                info[0] = fps;
                info[1] = (float) Commons.streamDouble(lostFrameRate * 100);
            }else {
                System.err.println("【ERROR】无FPS信息,请确认手机正常连接或APP正常运行");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return info;
    }

    public static double getFps(String deviceName,String packageName){
        return getInfo(deviceName,packageName)[0];
    }

    public static double getLostFrameRate(String deviceName,String packageName){
        return getInfo(deviceName,packageName)[1];
    }
}

  • 运行结果:

专项测试自动化-如何自动化获取APP的FPS、丢帧率等信息来测试流畅度(基于Android,Java)_第1张图片

另外再提供一个参考文档:移动性能测试 FPS 计算方法的比较

你可能感兴趣的:(自动化测试,专项测试/自动化,测试原理和设计,性能测试)