测试架构师之路---实际工作中如何开展Android App性能自动化测试

技术是互联网企业的核心,不管你怎么折腾最终还是以产品质量来说话,万变不离其宗;随着产品构造越来越复杂,对开发人员,对测试人员来说都是一个不小的挑战,这篇博客结合我的项目经验分享一下针对APP性能测试的方法


一直以来对于一个互联网产品,尤其是移动端的App,有一个长期争执的讨论;用户第一注重的到底是丰富实用的功能呢,还是体验优质的性能;我觉得对于测试来说这两者应该是平级,为什么不能将功能性能结合到一起来测试呢?实现的思路很简单,之前我也分享过一篇app自动化测试的博客,接下来要做的就是进行UI自动化的同时获取性能数据,对于一个Android App来说,它的性能数据(per数据)主要分为四大项:CPU占用率(运行时),Pss(实际物理运行内存),Net(流量消耗),power(电量消耗);因为这个power我们必须舍弃传统的数据线连接方式,测试过程中要保证手机设备不接受任何方式的充电操作


基于以上分析,我们将使用异常强大的ADB进行per数据的获取,ADB全称Android Debug Bridge,是一个非常全面的Android软件调试框架,它包含许多丰富的命令,首先我们搭建好ADB开发环境(具体步骤可以百度),然后确保测试用的手机和服务器 (如果是本地那就是你得本机)处在相同网络环境下,然后开启手机USB调试,在服务器或者本机命令行中输入“adb connect  手机IP:5555”(将“手机IP替换成测试手机的ip地址”),然后使用“adb devices”命令查看。如图测试架构师之路---实际工作中如何开展Android App性能自动化测试_第1张图片

这个“192.168.199.179:5555“”就是手机的device_id,这样就完成了无线连接调试,可以放心的去进行下一步;完成了移动设备连接后,我们就要开始进行测试代码的编写了,上面说了需要结合UI自动化测试,也就是说获取per是要和UI自动化同步进行的,所以这里就要引用多线程的方式去编写脚本,下面用一个简单的例子说明整个脚本的流程

# -*- coding: utf-8 -*-
import selenium
from appium import webdriver
import os
import time
import unittest
import HTMLParser

#Appium环境配置
PATH = lambda p: os.path.abspath(
    os.path.join(os.path.dirname(__file__), p)
)

class JdANDROIDTests(unittest.TestCase):
    def setUp(self):
        desired_caps = {}
        desired_caps['platformName'] = 'Android' #设置平台
        desired_caps['platformVersion'] = '6.0.1' #系统版本
        desired_caps['deviceName'] = '192.168.199.179:5555'
        desired_caps['autoLaunch'] = 'true' #是否自动启动
        desired_caps['appPackage'] = 'com.Jd' #包名
        desired_caps['appActivity'] = 'com.Jd.splash.SplashActivity'
        desired_caps['unicodeKeyboard'] = 'true'
        desired_caps['resetKeyboard'] = 'true'
        self.driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
        self.x = self.driver.get_window_size()['width']
        self.y = self.driver.get_window_size()['height']

def test_mjd(self):
    time.sleep(5)
    self.driver.get('https://m.jd.com/')
    time.sleep(3)
    search = self.driver.find_element_by_xpath('.//*[@id="index_newkeyword"]')
    search.click()
    search.send_keys('iwatch')
    self.driver.find_element_by_xpath('.//*[@id="index_search_submit"]/span').click()
    for i in range(1,5):
        time.sleep(3)
        pro = './/*[@id="searchlist44"]/li['+str(i)+']/a/div[2]/div[1]/span'
        self.driver.find_element_by_xpath(pro).click()
        time.sleep(3)
        self.driver.find_element_by_xpath('.//*[@id="cart1"]/div[2]/a[1]').click()
        if i<4:
            time.sleep(3)
            self.driver.find_element_by_xpath('.//*[@id="m_common_header_goback"]/span').click()
    time.sleep(3)
    num = int(self.driver.find_element_by_xpath('.//*[@id="carNum"]').text)
    if num == i:
        print u'购物车已添加'+str(num)+u'件商品'
    else:
        print u'购物车商品数量不对,请联系相关人员查看'

这段代码是个简单的京东商城多次添加购物车的操作UI自动化测试,下面我们在写一个获取per数据(这里只举cpu,电量和内存,流量获取方式比较复杂不在这里占用篇幅了)

的模块:

def get_cpu(packgename,device_id):
    try:
        #获取App的CPU占用率的adb命令
        re_command = 'adb -s device_id shell dumpsys cpuinfo | grep packgename'
        command = re_command.replace('device_id',device_id).replace('packgename',packgename).split(' ')
        # 使用python自带包subprocess开启一个子线程执行shell命令,并读取输出,将标准输出存入本地文件
        file = os.path.abspath('.') + datetime.now().strftime('%Y%m%d%H%M%S') + 'Pss.log'
        f = open(file, 'wb')
        p = subprocess.Popen(args=command,stdout=f,stderr=subprocess.PIPE)
        p.wait()
        f.closed
    except EOFError,E:
        print E

def get_Pss(packgename,device_id):
    try:
        # 获取App的物理运行内存的adb命令
        re_command = 'adb -s device_id shell dumpsys meminfo | grep packgename'
        command = re_command.replace('device_id', device_id).replace('packgename', packgename).split(' ')
        # 使用python自带包subprocess开启一个子线程执行shell命令,并读取输出,将标准输出存入本地文件
        file = os.path.abspath('.')+datetime.now().strftime('%Y%m%d%H%M%S')+'Pss.log'
        f = open(file,'wb')
        p = subprocess.Popen(args=command, stdout=f, stderr=subprocess.PIPE)
        p.wait()
        f.closed
    except EOFError, E:
        print E

def get_power(device_id):
    try:
        # 获取电量的adb命令
        re_command = 'adb -s device_id shell dumpsys battery'
        command = re_command.replace('device_id', device_id).split(' ')
        # 使用python自带包subprocess开启一个子线程执行shell命令,并读取输出,将标准输出存入本地文件
        file = os.path.abspath('.')+datetime.now().strftime('%Y%m%d%H%M%S')+'Pss.log'
这三段是简单的将获取的性能数据存入到本地文件中,当然最后的做法是存入到数据库,由于占用篇幅过大就不再举例了;下面我们就将这三段脚本和上面的UI自动化测试脚本同步执行吧,需要用到python的多线程模块threading,如下:

def thead_main():
    #构造多线程对象执行池,对象接收一个要执行的方法名,如果方法需要传参通过args选项实现
    theads = []
    t1 = threading.Thread(target=test_mjd)
    theads.append(t1)
    t2 = threading.Thread(target=get_cpu,args=('com.Jd','192.168.199.179:5555'))
    theads.append(t2)
    t3 = threading.Thread(target=get_Pss, args=('com.Jd', '192.168.199.179:5555'))
    theads.append(t3)
    t4 = threading.Thread(target=get_power, args=('192.168.199.179:5555',))
    theads.append(t4)
    for t in theads:
        t.start()   #start方法开启一个执行池的运行
        
if __name__ == '__main__':
    thead_main()
到这里我们就完美实现了同步测试App的功能和性能,当然这个例子举得非常简单,后续还有分别编写测试报告以及更深入的测试步骤;不过在你技术熟练了之后,这些都不是问题。


通过这篇博客我想建议的是,在做这些测试的时候尽可能的要脱离一些工具(比如腾讯的gt),要自己去写,这样才会熟练,这样才是属于你自己的框架


     

你可能感兴趣的:(测试)