Android SDK 自动化性能测试方案: SDK + Appium + Emmagee + Python

一、前情概要

但凡接触过性能测试的都对以下情景深有体会:
 1.测试前置工作量大繁琐,手工操作费时费力;
 2.测试结果有出入,自己想再确认一下,测试过程再来一遍吧;好不容易整出了一份报告,RD一看对结果不满意存在质疑,来回修改几遍整个测试过程就需要再来几遍,整个过程下来精疲力竭;
 3.性能数据整理细致入微,测试5分钟,数据整理2小时,一顿操作下来眼睛要瞎;

二、项目背景

为了减少以上痛苦对身体带来的一万点暴击伤害,以及从整个测试模式、方法来看,急需要一套自动化性能测试方案来提高整个性能测试的效率;同时随着DevOps(DevOps 强调的是高效组织团队之间如何通过自动化的工具协作和沟通来完成软件的生命周期管理,从而更快、更频繁地交付更稳定的软件)在各个一二线大厂的推行,性能测试任务接入流水线用于周期性触发执行也是大势所趋,因此一套全自动化的性能测试方案亟待推出用于解决工作的难点问题,提高整个的工作效率。

三、解决的主要问题

 1.测试过程繁琐,人工介入成本高;
 2.测试结果有出入,自己想再确认一下,测试过程再来一遍吧;好不容易整出了一份报告,RD一看对结果不满意存在质疑,来回修改几遍整个测试过程就需要再来几遍,整个过程下来精疲力竭;
 3.性能数据整理细致入微,测试5分钟,数据整理2小时,一顿操作下来眼睛要瞎;

四、实现方案

整体框架:

Python + Appium + Emmagee

实现原理:

Python脚本实现Appium对Emmagee的驱动-》进而调起测试APP中的测试场景和case-》运行-》性能测试数据自动读取-》数据统计、分析-》输出测试报告

实现场景:

目前已实现支持基础地图、个性化地图、热力图、海量Polyline地图场景下放大、缩小、拖拽等多种操作下的性能数据的全自动输出

Demo示例:
第一步:材料准备

1.待测APP/待测场景

image.png

2.Emmage性能测试工具
3.Appium工具
4.Python 3.7环境

第二步:按步骤来实现每个阶段的自动化

明确要实现自动化的操作步骤,如上面实现原理所描述的"当准备好待测APP/待测场景后,实现操作-》运行-》数据收集-》统计分析-》输出报告"的全自动化,因此按步骤来实现每个阶段的自动化。
1.Python脚本实现Appium对Emmagee的驱动

# performance_test_tool.py
import os
import shutil
import time
from appium import webdriver
from appium.webdriver.common.touch_action import TouchAction
from auto_analysis_tool import analysis_output_test_report

"""
入参说明:
open_dir_path:Emmagee 输出的原始性能数据文件所在目录(文件按修改时间降序排列)
output_file_name:最终输出的性能数据报告文件名名称和所在路径
start_line:截取原始性能数据文件开始行
end_line:截取原始性能数据文件结束行

"""
def start_testing(open_dir_path, output_file_name, start_line, end_line):
    # appium服务监听地址
    server = 'http://localhost:4723/wd/hub'

    # app启动参数
    desired_caps = {
        # "platformName": "Android",
        # "platformVersion": "6.0",
        # "deviceName": "T7G0215A31011599",
        # "appPackage": "com.netease.qa.emmagee",
        # "appActivity": ".activity.MainPageActivity",
        # # "appWaitActivity": ".activity.MainPageActivity",
        # # "appWaitPackage": "com.netease.qa.emmagee",
        # "appiumVersion": "2.5.1"

        "platformName": "Android",
        "platformVersion": "5.1.1",
        "deviceName": "T3Q4C16A17003811",
        "appPackage": "com.netease.qa.emmagee",
        "appActivity": ".activity.MainPageActivity"
    }
    desired_caps['unicodeKeyboard'] = True
    desired_caps['resetKeyboard'] = True

    # 驱动
    driver = webdriver.Remote(server, desired_caps)

    # 点击设置按钮
    driver.find_element_by_id("com.netease.qa.emmagee:id/btn_set").click()

    time.sleep(2)

    # 设置采集频率为1s
    TouchAction(driver).tap(x=97, y=449).perform()

    # 点击返回按钮
    driver.find_element_by_id("com.netease.qa.emmagee:id/go_back").click()

    time.sleep(5)

    # 获取测试APP RadioButton
    radio_button = driver.find_element_by_xpath(
        "/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.ListView/android.widget.LinearLayout[5]/android.widget.RadioButton")

    radio_button = driver.find_element_by_xpath("/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.ListView/android.widget.LinearLayout[8]/android.widget.RadioButton")

    # 选中测试APP RadioButton
    radio_button.click()

    # 点击开始测试按钮
    driver.find_element_by_id("com.netease.qa.emmagee:id/test").click()

    # 运行测试场景,如1分钟
    time.sleep(60)

    # 点击停止测试按钮
    TouchAction(driver).tap(x=453, y=286).perform()

    # kill测试Demo
    os.system("adb shell am force-stop baidumapsdk.demo")

    time.sleep(5)

    # 清除目标目录下的文件
    del_file("./Emmagee/")

    # adb pull 生成的测试报告到目标文件夹下
    os.system("adb pull /sdcard/Emmagee/ ./")

    # 解析测试报告内容:内存、CPU信息,并输出分析后的测试报告
    analysis_output_test_report(open_dir_path, output_file_name, start_line, end_line)

    # 关闭会话
    driver.quit()


"""清空文件夹内容"""


def del_file(filepath):
    """
    删除某一目录下的所有文件或文件夹
    :param filepath: 路径
    :return:
    """
    if os.path.isdir(filepath):
        del_list = os.listdir(filepath)
        for f in del_list:
            file_path = os.path.join(filepath, f)
            if os.path.isfile(file_path):
                os.remove(file_path)
            elif os.path.isdir(file_path):
                shutil.rmtree(file_path)

2.性能数据收集、解析、输出报告

'''
# auto_analysis_tool.py
自动化工具:自动解析原始性能报告并输出分析后的测试报告
'''
import os
import csv
import numpy

"""
对外暴露接口:解析测试报告内容:内存、CPU信息,并输出分析后的测试报告
"""


def analysis_output_test_report(open_dir_path, output_file_name, start_line, end_line):
    # 获取原始测试报告文件路径
    origin_file_path = get_report_path(open_dir_path)
    # 打开原始测试报告文件
    file = open(origin_file_path, encoding="gbk")
    # 读取内容并解析cpu/memory信息
    data = csv.reader(file)
    cpu = []
    memory = []
    for row in data:
        if data.line_num < start_line:
            continue
        # 只获取指定count_number行
        if data.line_num > end_line:
            break
        cpu.append(float(row[5]))  # 将字符串数据转化为浮点型加入到数组之中
        memory.append(float(row[2]))
        print(data.line_num, row)

    cpu_mean = numpy.mean(cpu)  # 输出cpu均值
    cpu_max = max(cpu)  # 输出cpu最大值

    memory_mean = numpy.mean(memory)  # 输出memory均值
    memory_max = max(memory)  # 输出memory最大值

    print(cpu_mean)
    print(cpu_max)

    print(memory_mean)
    print(memory_max)

    # 以约定格式输出性能数据
    write_analysis_report(output_file_name, cpu_mean, cpu_max, memory_mean, memory_max)

    file.close()


"""
获取测试报告文件路径
"""


def get_report_path(open_file_path):
    dir_list = os.listdir(open_file_path)  # 列出文件夹下所有的目录与文件
    if not dir_list:
        return
    else:
        # 注意,这里使用lambda表达式,将文件按照最后修改时间顺序升序排列
        # os.path.getmtime()  函数是获取文件最后修改时间
        # os.path.getctime() 函数是获取文件最后创建时间
        dir_list = sorted(dir_list, key=lambda x: os.path.getmtime(os.path.join(open_file_path, x)), reverse=True)

        test_report_path = os.path.join(open_file_path, dir_list[0])  # 获取Emmagee最新生成的测试报告文件
        print(test_report_path)
        return test_report_path


'''输出分析后的测试报告'''


def write_analysis_report(output_file_name, cpu_mean, cpu_max, memory_mean, memory_max):
    with open(output_file_name, 'w', encoding="gbk") as file_object:
        file_object.write(
            "cpu_mean:" + str(cpu_mean) + "\t" + "cpu_max:" + str(cpu_max) + "\t" + "memory_mean:" + str(
                memory_mean) + "\t" + "memory_max:" + str(memory_max))

3.单个测试case运行

# test_case1.py
from performance_test_tool import start_testing

start_testing("/Users/username/Documents/workSpace/PerformAutoTesting/Emmagee/",
             "/Users/username/Documents/workSpace/PerformAutoTesting/outputReport/case1.txt", 11,
              12)

4.性能报告文件输出

# case1.txt
cpu_mean:17.495 cpu_max:27.59   memory_mean:89.375  memory_max:98.31

5.附件(Emmagee原始性能数据文件示例.csv)


image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容