IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android APP性能测试(APP冷、热启动测试) -> 正文阅读

[移动开发]Android APP性能测试(APP冷、热启动测试)

ODM项目为了测试平台稳定性,会下载大量第三方app进行冷、热启动的测试,并生成测试报告。

根据测试结果可用于暴露平台性能上的一些缺陷。

实现:pythn+adb

以下分享源码实现过程

# !/usr/bin/python
# -*- coding: utf-8 -*-
# jianfeng.qian
import subprocess
import re
import glob
import os
import time
import xlsxwriter
from numpy import *

root = os.getcwd()
TEST_APP_CONFIG_DIR = 'test_app_config'
wait_time = 'WaitTime:'
launcher_state = 'LaunchState:'
status = 'Status:'

ITEM_TEST_TIMES = 2
APPS_START_COLD = 'COLD'
APPS_START_HOT = 'HOT'

devices_list_finally = []

skip_apps_install_list = []
EXCEL_RESULT_INFO = "EXCEL_RESULT_INFO_%s.xlsx"
EXCEL_RESULT_INFO_TITLE = ["APK NAME", "PACKAGE NAME", "ACTIVITY NAME", "LAUNCHER STATE", "WAIT TIME"]

EXCEL_RESULT_MEAN = "EXCEL_RESULT_MEAN_%s.xlsx"
EXCEL_RESULT_MEAN_TITLE = ["APK NAME", "PACKAGE NAME", "ACTIVITY NAME", "COLD WAIT TIME MEAN", "HOT WAIT TIME MEAN",
                           "COLD WAIT TIME MAX", "HOT WAIT TIME MAX"]

UNTESTED_LIST = "Untested_list_%s.txt"
special_dit = {"com.facebook.katana": "com.facebook.katana.activity.FbMainTabActivity",
               "com.instagram.android": "com.instagram.android.activity.MainTabActivity",
               "com.facebook.orca": "com.facebook.orca.auth.StartScreenActivity",
               "com.google.android.youtube": "com.google.android.youtube.HomeActivity",
               "com.snapchat.android": "com.snapchat.android.LandingPageActivity"}
"""
def resource_path(relative):
    if hasattr(sys, "_MEIPASS"):
        return os.path.join(sys._MEIPASS, relative)
    return os.path.join(relative)
AAPT = resource_path(os.path.join("%s.exe" % "aapt"))
print(AAPT)
"""
# 测试数据采集
APK_NAME_LIST = []
PACKAGE_NAME_LIST = []
ACTIVITY_NAME_LIST = []
LAUNCHER_STATE_LIST = []
WAIT_TIME_LIST = []
EXCEL_LINE_LIST = []  # 导入excel 总表

# 测试平均数据采集
APK_NAME_LIST_MEAN = []
PACKAGE_NAME_LIST_MEAN = []
ACTIVITY_NAME_LIST_MEAN = []
COLD_WAIT_TIME_MEAN = []
HOT_WAIT_TIME_MEAN = []
COLD_WAIT_TIME_MAX = []
HOT_WAIT_TIME_MAX = []
EXCEL_LINE_LIST_MEAN = []  # 导入excel 总表
VERSION_SDK = ""

"""
class AppInfoConfig():
    def __init__(self, apkPath):
        self.apkPath = apkPath

    def getApkBaseInfo(self):
        p = subprocess.Popen(
            "aapt dump badging %s" % (self.apkPath),
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            stdin=subprocess.PIPE, shell=True)
        (output, err) = p.communicate()
        result = []
        # lineList = ""
        for x in output.decode().splitlines():
            if 'package: name=' in x:
                match = re.compile("package: name='(\S+)'").match(x)
                if not match:
                    raise Exception("can't get packageinfo")
                packagename = match.group(1)
                # lineList += "package=%s\n" % packagename
                result.append(packagename)
            elif 'launchable-activity: name=' in x:
                match = re.compile("launchable-activity: name='(\S+)' ").match(x)
                if not match:
                    raise Exception("can't get packageinfo")
                launchable_activity = match.group(1)
                # lineList += "activity=%s\n" % launchable_activity
                result.append(launchable_activity)
        # file_name = "%s\%s\%s.config" % (root, TEST_APP_CONFIG_DIR, packagename)
        # with open(file_name, "w") as f1:
        #    f1.write(lineList)
        p.communicate()
        return result
"""


class AppInfoConfig():
    def __init__(self, apkPath):
        self.apkPath = apkPath

    def find_str(self, find_name, sourceStr):
        res = re.findall(find_name, sourceStr)
        name = res[0]
        return name

    def check_package_name(self, result, packageName):
        for k, v in special_dit.items():
            if packageName == k:
                result.append(v)
                return True
        return False

    def getApkBaseInfo(self):
        p = subprocess.Popen(
            "aapt dump badging %s" % (self.apkPath),
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            stdin=subprocess.PIPE, shell=True)
        (output, err) = p.communicate()
        result = []
        for x in output.decode().splitlines():
            if 'package: name=' in x:
                packagename = self.find_str("package: name='(.+?)'", x)
                result.append(packagename)
                if self.check_package_name(result, packagename):
                    break
                """
                if packagename == "com.facebook.katana":
                    result.append("com.facebook.katana.activity.FbMainTabActivity")
                    break
                elif packagename == "com.instagram.android":
                    result.append("com.instagram.android.activity.MainTabActivity")
                    break
                elif packagename == "com.facebook.orca":
                    result.append("com.facebook.orca.auth.StartScreenActivity")
                    break
                elif packagename == "com.google.android.youtube":
                    result.append("com.google.android.youtube.HomeActivity")
                    break
                elif packagename == "com.snapchat.android":
                    result.append("com.snapchat.android.LandingPageActivity")
                    break
                """
            elif 'launchable-activity: name=' in x:
                launchable_activity = self.find_str("launchable-activity: name='(.+?)'", x)
                result.append(launchable_activity)
        p.communicate()
        return result


def execCmd(cmd):
    r = os.popen(cmd)
    return r.read()


def match_info(a, b):
    match = re.compile("%s (\S+)" % a).match(b)
    return match.group(1)


def connectDevcie():
    global VERSION_SDK
    result = os.popen('adb devices').read().strip()
    if len(result.splitlines()) == 1:
        print("ADB Connect Error!")
        return False
    else:
        VERSION_SDK = os.popen("adb shell getprop ro.build.version.sdk").read().strip()
        print("ADB Connect successful. version SDK : %s" % VERSION_SDK)
        """
        adb_root_status = execCmd('adb root & adb remount').splitlines()
        for x in adb_root_status:
            
            if 'remount succeeded' in x or 'adbd is already running as root' in x:
                print("ADB root successful.")
                return True
            
            return True
        """
        return True


def stat_app(startmode, package, activity):
    item_test_result = []
    start_cmd = ""
    if startmode == APPS_START_COLD:
        start_cmd = 'adb shell am start-activity -S -W'
    elif startmode == APPS_START_HOT:
        start_cmd = "adb shell am start-activity -W "
    start = execCmd("%s %s/%s" % (start_cmd, package, activity))  # 冷启动
    for x in start.splitlines():
        if wait_time in x:
            result = "%s %s " % (wait_time, match_info(wait_time, x))
            item_test_result.append(result)
        elif launcher_state in x:
            result = "%s %s " % (launcher_state, match_info(launcher_state, x))
            item_test_result.append(result)
        elif status in x:
            result = "%s %s " % (status, match_info(status, x))
            item_test_result.append(result)

    # os.system("adb shell am start-activity -W %s/%s" % (package, activity))
    time.sleep(3)
    if startmode == APPS_START_COLD:
        execCmd("adb shell am force-stop %s " % package)
        time.sleep(5)
        # execCmd("adb shell \"echo 3 > /proc/sys/vm/drop_caches\"") # user版本下无法使用
        execCmd("adb shell cmd package compile -m speed-profile -f %s" % package)
    elif startmode == APPS_START_HOT:
        execCmd("adb shell input keyevent 3")
    # print(item_test_result)
    if VERSION_SDK == "29":
        time.sleep(10)
    return item_test_result


def get_apks_list(file_dir):
    file_list = []
    files = glob.glob(file_dir + '/*')
    index = 0
    for file in files:
        if os.path.splitext(file)[1] == '.apk':
            index += 1
            file_list.append("%s,%s" % (index, os.path.join(root, file)))
            # file_list.sort()
    return file_list


def write_excel(title, data, file):
    workbook = xlsxwriter.Workbook(file)
    worksheet = workbook.add_worksheet(u'sheet1')
    worksheet.set_row(0, 30)
    worksheet.set_column(0, 100, 70)
    count = 0
    for i in range(ord("A"), ord("Z") + 1):
        if count == len(title):
            break
        worksheet.write("%s1" % chr(i), title[count], workbook.add_format({
            'bold': True, 'border': 3, 'align': 'center', 'valign': 'vcenter', 'fg_color': '#019285',
            'font_color': '#FFFFFF'
        }))
        count += 1

    count_line = 0
    for x, one in enumerate(data):
        for y, i in enumerate(one):
            worksheet.set_column(y + 1, x, len(i) + 20)
            if title[x] == "ACTIVITY NAME" or title[x] == "PACKAGE NAME":
                worksheet.set_column(y + 1, x, 100)
            worksheet.write(y + 1, x, i, workbook.add_format({
                'bold': False, 'border': 1, 'valign': 'vcenter', 'fg_color': '#ECECEC',
                'font_color': '#000000'
            }))
        count_line += 1
    workbook.close()


def test(apk_name, package, activity, test_mode):
    wait_t = []
    for times in range(ITEM_TEST_TIMES):
        try:
            result_info = stat_app(test_mode, package, activity)
            print("Start app %s test (%s/%s) , info =  %s" % (test_mode, times + 1, ITEM_TEST_TIMES, result_info))
            APK_NAME_LIST.append(apk_name)
            PACKAGE_NAME_LIST.append(package)
            ACTIVITY_NAME_LIST.append(activity)  # .split(".")[-1] 获取最后class name
            LAUNCHER_STATE_LIST.append(result_info[1].split(":")[1])
            WAIT_TIME_LIST.append(result_info[2].split(":")[1])
            wait_t.append(int(result_info[2].split(":")[1]))
        except Exception:
            # print(Exception)
            return None
    return wait_t


def build_txt(path, list):
    lineList = ""
    for x in list:
        lineList += x + "\n"
    with open(path, "w") as f:
        f.write(lineList)


def check_install(apk_file, apk_name, result):
    print("%s Install %s" % (apk_name, result))
    for x in result.splitlines():
        if "failed to install" in x or "Install Failure" in x:
            skip_apps_install_list.append(apk_file)
            return True
    return False


def do_test():
    apks_list = get_apks_list(root)
    for apk_file in apks_list:
        test_index, apk_file = apk_file.split(",")
        appinfo = AppInfoConfig(apk_file).getApkBaseInfo()
        package = appinfo[0]
        apk_name = os.path.basename(apk_file)
        is_installed = False
        try:
            activity = appinfo[1]
        except:
            print("Apk parse error %s " % apk_file)
            skip_apps_install_list.append(apk_file)
            continue

        print("Start test (%s/%s) apkName = %s , packageName = %s "", ActivityLauncher = %s " % (
            test_index, len(apks_list), apk_name, package, activity))
        # Step 1 check apk install
        force_install_apps = os.popen("adb shell pm list packages %s" % package).read().strip()
        if package in force_install_apps:
            # print("Apk file %s  installed" % apk_file)
            # skip_apps_install_list.append(apk_file)
            # continue
            print("Apk file %s  installed" % apk_file)
            is_installed = True
        # Step 2 install apk
        if not is_installed:
            installed = execCmd("adb install -r -d -g %s 2>&1" % apk_file)  # 冷启动
            if check_install(apk_file, apk_name, installed):
                continue
            time.sleep(10)  # 延迟60秒

        # Step 3 install apk
        # 冷启动app测试
        result_cold = test(apk_name, package, activity, APPS_START_COLD)
        if result_cold == None:
            skip_apps_install_list.append(apk_file)
            continue

        # 平均值计算,收集
        APK_NAME_LIST_MEAN.append(apk_name)
        PACKAGE_NAME_LIST_MEAN.append(package)
        ACTIVITY_NAME_LIST_MEAN.append(activity)
        COLD_WAIT_TIME_MEAN.append('%s' % round(mean(result_cold), 2))
        COLD_WAIT_TIME_MAX.append('%s' % round(max(result_cold), 2))
        # 测试热启动前,预启动应用
        stat_app(APPS_START_HOT, package, activity)  # 预启动
        # 热启动app测试
        result_hot = test(apk_name, package, activity, APPS_START_HOT)
        if result_hot == None:
            skip_apps_install_list.append(apk_file)
            continue
        HOT_WAIT_TIME_MEAN.append('%s' % round(mean(result_hot), 2))
        HOT_WAIT_TIME_MAX.append('%s' % round(max(result_hot), 2))
        # 卸载测试apk
        if not is_installed:
            uninstall_apps = os.popen("adb uninstall %s" % package).read().strip()
            print(uninstall_apps)

    # 统计测试源码数据
    current_time = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time()))
    EXCEL_LINE_LIST.append(APK_NAME_LIST)
    EXCEL_LINE_LIST.append(PACKAGE_NAME_LIST)
    EXCEL_LINE_LIST.append(ACTIVITY_NAME_LIST)
    EXCEL_LINE_LIST.append(LAUNCHER_STATE_LIST)
    EXCEL_LINE_LIST.append(WAIT_TIME_LIST)

    EXCEL_LINE_LIST_MEAN.append(APK_NAME_LIST_MEAN)
    EXCEL_LINE_LIST_MEAN.append(PACKAGE_NAME_LIST_MEAN)
    EXCEL_LINE_LIST_MEAN.append(ACTIVITY_NAME_LIST_MEAN)
    EXCEL_LINE_LIST_MEAN.append(COLD_WAIT_TIME_MEAN)
    EXCEL_LINE_LIST_MEAN.append(HOT_WAIT_TIME_MEAN)
    EXCEL_LINE_LIST_MEAN.append(COLD_WAIT_TIME_MAX)
    EXCEL_LINE_LIST_MEAN.append(HOT_WAIT_TIME_MAX)

    # 生成测试源数据excel表格
    write_excel(EXCEL_RESULT_INFO_TITLE, EXCEL_LINE_LIST, EXCEL_RESULT_INFO % current_time)
    # 生成平均值excel表格
    write_excel(EXCEL_RESULT_MEAN_TITLE, EXCEL_LINE_LIST_MEAN, EXCEL_RESULT_MEAN % current_time)
    # 输出未测试的apk列表
    print("app installed skip install list \n%s" % skip_apps_install_list)

    build_txt(UNTESTED_LIST % current_time, skip_apps_install_list)


if __name__ == '__main__':
    """
    apk_list = get_apks_list(root)
    for x in apk_list:
        print(x)
        AppInfoConfig(x).getApkBaseInfo()
    """
    ITEM_TEST_TIMES = int(input("请输入单个apk测试次数(默认冷热启动各50次)"))
    if connectDevcie():
        do_test()

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-07-23 10:54:40  更:2021-07-23 10:55:17 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年4日历 -2024/4/28 22:40:11-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码