├── .idea
├── .name
├── AppPerformance.iml
├── misc.xml
├── modules.xml
└── vcs.xml
├── PerConfig.py
├── README.md
├── lib
├── AppAdbCom.py
├── AppDevInfo.py
├── AppMonitor.py
├── AppOperateFile.py
├── AppOperatePick.py
├── AppReport.py
└── __init__.py
├── monkey_stop.py
├── report.png
├── report
├── APU0215C08002952_com.aliyun.alink_Medium_report.html
└── __init__.py
└── testCase
├── ManualTest.py
├── MonkeyTest.py
└── __init__.py
/.idea/.name:
--------------------------------------------------------------------------------
1 | AppPerformance
--------------------------------------------------------------------------------
/.idea/AppPerformance.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/PerConfig.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: UTF-8 -*-
3 |
4 | import random,os
5 |
6 | class AppPerCon(object):
7 | # apk包名
8 | package_name = "com.aliyun.alink"
9 | # 活动名
10 | alink_Activity = 'com.aliyun.alink/.page.main.MainActivity'
11 | # 默认设备列表
12 | device_dict = {}
13 | #手机安装应用默认UID,通过adb进行查询可获得
14 | appuid = {'MATE8':{'com.robam.roki':'10274','com.UCMobile':'10156','com.aliyun.alink':'10222'},
15 | 'MATE10':{'com.robam.roki': '10164', 'com.UCMobile':'10138','com.aliyun.alink':'10145'}
16 | }
17 | # 网络
18 | net = "wifi"
19 | # monkey seed值,随机产生
20 | # monkey_seed = str(random.randrange(1, 1000))
21 | monkey_seed = 200
22 | # monkey 参数
23 | monkey_parameters_full = "--throttle 50 --ignore-crashes --ignore-timeouts --pct-touch 80 --pct-trackball 5 --pct-appswitch 9 --pct-syskeys 1 --pct-motion 5 -v -v -v 1000"
24 | monkey_parameters_medi = "--throttle 150 --ignore-crashes --ignore-timeouts --pct-touch 80 --pct-trackball 5 --pct-appswitch 9 --pct-syskeys 1 --pct-motion 5 -v -v -v 2500"
25 | #monkey_parameters = "--throttle 500 -v -v -v 500"
26 | # log保存地址
27 | log_location = os.path.dirname(os.path.realpath(__file__))+"\log"
28 | #性能数据存储目录
29 | info_path = os.path.dirname(os.path.realpath(__file__))+"\info" + "\\"
30 | # report保存地址
31 | report_path = os.path.dirname(os.path.realpath(__file__)) + "\\report\\"
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 需要安装依赖包pyecharts,安装方法百度即可
2 |
3 | 打开PerConfig,修改pack_name为你需要测试的APP包名,如要测试UC浏览器即改为'com.UCMobile',xxx_Activity为APP主活动,比如UC浏览器的主活动名称为'com.UCMobile/.main.UCMobile',这里改为你自己的活动名称即可,使用adb命令即可查看,详细步骤可上网百度一下
4 | # AppPerformance
5 |
6 | Android移动端性能测试工具
7 |
8 | 连接上手机直接运行testcase下的MonkeyTest.py 即可,自动生成测试报告
9 |
10 | devicename_com.aliyun.alink_Medium_report
11 |
12 | 效果如下:
13 |
14 | 
15 |
--------------------------------------------------------------------------------
/lib/AppAdbCom.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: UTF-8 -*-
3 | import os,time,subprocess
4 | from PerConfig import AppPerCon
5 |
6 | class AdbDebug(object):
7 | #adb通用处理函数
8 | # def adbCommon(self,target):
9 | # list = self.checkDevices()
10 | # count = len(list)
11 | # if target + 1 > count:
12 | # print "请确认连接手机数量,输入正确的序号,0为第一台,依此类推"
13 | # return
14 | # return list
15 |
16 |
17 | def call_adb(self, command):
18 | result = ''
19 | command_text = "adb %s" % (command)
20 | results = os.popen(command_text, "r")
21 | while True:
22 | line = results.readline()
23 | if not line:
24 | break
25 | result += line
26 | results.close()
27 | return result
28 |
29 | def checkDevices(self):
30 | res = self.call_adb("devices")
31 | devices = res.partition('\n')[2].replace('\n', '').split('\tdevice')
32 | return [device for device in devices if len(device) > 2]
33 |
34 | #停止adb服务
35 | def adbStop(self):
36 | return self.call_adb("kill-server")
37 |
38 | #开启adb服务
39 | def adbStart(self):
40 | return self.call_adb("start-server")
41 |
42 | #查看adb版本
43 | def adbVersion(self):
44 | return self.call_adb("version")
45 |
46 | #开启adb网络调试接口(需连接USB线)
47 | def adbTcp(self, target):
48 | return self.call_adb("-s %s tcpip 5555"% (target))
49 |
50 | #网络调试连接
51 | def adbNetConOpen(self, target, address):
52 | return self.call_adb("-s %s connect %s" % (target, address))
53 |
54 | #关闭网络调试连接
55 | def adbNetConClose(self, target, address):
56 | return self.call_adb("-s %s disconnect %s" % (target, address))
57 |
58 |
59 | # 将电脑文件拷贝到手机里面
60 | # [电脑上的目录] < 设备里的文件路径 >
61 | def push(self, target, local, remote):
62 | result = self.call_adb("-s %s push %s %s" % (target, local, remote))
63 | return result
64 |
65 |
66 | # 拉数据到本地
67 | # < 设备里的文件路径 > [电脑上的目录]
68 | def pull(self, target, remote, local):
69 | result = self.call_adb("-s %s pull %s %s" % (target, remote, local))
70 | return result
71 |
72 | #电脑端安装应用
73 | # -l 将应用安装到保护目录 / mnt / asec
74 | # -r 允许覆盖安装
75 | # -t 允许安装AndroidManifest.xml里application指定android:testOnly = "true"的应用
76 | # -s 将应用安装到sdcard
77 | # -d 允许降级覆盖安装
78 | # -g 授予所有运行时权限
79 | def adbInstallApk(self, target, local):
80 | return self.call_adb("-s %s install %s"(target, local))
81 |
82 | def adbInstallApk(self, var, local):
83 | return self.call_adb("install "+ var + local)
84 |
85 | #电脑端卸载应用
86 | # < packname > 表示应用的包名,-k
87 | # 参数可选,表示卸载应用但保留数据和缓存目录。
88 | def adbUninstallApk(self, target, packName):
89 | return self.call_adb("-s %s uninstall %s" % (target, packName))
90 |
91 | def adbUninstallApk(self, target, var, packName):
92 | return self.call_adb("-s %s uninstall %s %s" % (target, var, packName))
93 |
94 |
95 | #查看应用列表
96 | # 无 所有应用
97 | # -f 显示应用关联的 apk 文件
98 | # -d 只显示 disabled 的应用
99 | # -e 只显示 enabled 的应用
100 | # -s 只显示系统应用
101 | # -3 只显示第三方应用
102 | # -i 显示应用的 installer
103 | # -u 包含已卸载应用
104 | def adbGetPmlist(self, target, var):
105 | return self.call_adb("-s %s shell pm list packages %s" % (target, var))
106 |
107 | # 清除应用数据缓存
108 | def adbCacheClear(self, target, packName):
109 | result = self.call_adb("-s %s shell pm clear %s" % (target, packName))
110 | return result.rstrip()
111 |
112 | # 查看应用详细信息
113 | def adbGetAppInfo(self, target, packName):
114 | result = self.call_adb("-s %s shell dumpsys package %s" % (target, packName))
115 | return result.strip()
116 |
117 | # 启动Activity
118 | def adbStartActivity(self, target, activity):
119 | result = self.call_adb("-s %s shell am start %s" % (target, activity))
120 | return result.rstrip()
121 |
122 | # 强制停止Activity
123 | def adbStopActivity(self, target, packName):
124 | result = self.call_adb("-s %s shell am force-stop %s" % (target, packName))
125 | return result.rstrip()
126 |
127 | # 获得设备型号
128 | def adbGetDeviceModel(self, target):
129 | result = self.call_adb("-s %s shell getprop ro.product.model" % (target))
130 | return result.rstrip()
131 |
132 | # 获取设备品牌
133 | def adbGetDeviceBrand(self, target):
134 | result = self.call_adb("-s %s shell getprop ro.product.brand" % (target))
135 | return result.rstrip()
136 |
137 | # 获得设备名称
138 | def adbGetDeviceName(self, target):
139 | result = self.call_adb("-s %s shell getprop ro.product.name" % (target))
140 | return result.rstrip()
141 |
142 |
143 | # 获得设备处理器型号
144 | def adbGetDeviceBoard(self, target):
145 | result = self.call_adb("-s %s shell getprop ro.product.board" % (target))
146 | return result.rstrip()
147 |
148 |
149 | # 设备重启
150 | def adbDeviceReboot(self, target):
151 | result = self.call_adb("-s %s reboot" % (target))
152 | return result.rstrip()
153 |
154 |
155 | # 获取电池状况
156 | def adbGetBattery(self, target):
157 | result = self.call_adb("-s %s shell dumpsys battery" % (target))
158 | return result.rstrip()
159 |
160 | # 获取屏幕分辨率
161 | def adbGetScreenSize(self, target):
162 | result = self.call_adb("-s %s shell wm size" % (target))
163 | return result.rstrip()
164 |
165 | # 获取屏幕dpi
166 | def adbGetScreenDPI(self, target):
167 | result = self.call_adb("-s %s shell wm density" % (target))
168 | return result.rstrip()
169 |
170 | # 获取屏幕参数
171 | def adbGetScreenInfo(self, target):
172 | result = self.call_adb("-s %s shell dumpsys window displays" % (target))
173 | return result.rstrip()
174 |
175 | # 获取Android系统版本
176 | def adbGetAndroidVersion(self, target):
177 | result = self.call_adb("-s %s shell getprop ro.build.version.release" % (target))
178 | return result.strip()
179 |
180 | # 获取IP地址
181 | def adbGetDevIP(self, target):
182 | result = self.call_adb("-s %s shell ifconfig wlan0" % (target))
183 | if int(self.adbGetAndroidVersion(target).split(".")[0]) > 4:
184 | if result.rsplit(":")[1][19:23] == "inet":
185 | return result.rsplit(":")[2][:13]
186 | else:
187 | print "WIFI未开启,请打开WIFI开关"
188 | return
189 | else:
190 | return result.rsplit(":")[1][4:17]
191 |
192 | # 获取MAC地址
193 | def adbGetDevMac(self, target):
194 | result = self.call_adb("-s %s shell cat /sys/class/net/wlan0/address" % (target))
195 | return result.strip()
196 |
197 | # 获取CPU信息
198 | def adbGetDevCPU(self, target):
199 | result = self.call_adb("-s %s shell cat /proc/cpuinfo" % (target))
200 | return result.strip()
201 |
202 |
203 | # 获取系统内存信息
204 | def adbGetDevMem(self, target):
205 | result = self.call_adb("-s %s shell cat /proc/meminfo" % (target))
206 | return result.strip()
207 |
208 |
209 | # 获取应用内存信息
210 | def adbGetDevPidMem(self, target, packname):
211 | result = self.call_adb("-s %s shell dumpsys meminfo %s" % (target, packname))
212 | return result.strip()
213 |
214 |
215 |
216 | # 获取总的CPU使用时间
217 | def adbGetCpuTime(self, target):
218 | result = self.call_adb("-s %s shell cat /proc/stat" % (target))
219 | return result.strip()
220 |
221 | # 获取进程CPU时间片
222 | def adbGetPidJiff(self, target, pid):
223 | result = self.call_adb("-s %s shell cat /proc/%s/stat" % (target, pid))
224 | return result.strip()
225 |
226 | # 获取进程fps
227 | def adbGetPidfps(self, target, packname):
228 | result = self.call_adb("-s %s shell dumpsys gfxinfo %s" % (target, packname))
229 | return result.strip()
230 |
231 | # 获取进程流量信息
232 | def adbGetPidflow(self, target, packname, flag):
233 | if int(self.adbGetAndroidVersion(target).split('.')[0]) < 8:
234 | uid = AppPerCon.appuid['MATE8'][packname]
235 | rec = self.call_adb("-s %s shell cat /proc/uid_stat/%s/tcp_rcv" % (target, uid)).strip()
236 | sen = self.call_adb("-s %s shell cat /proc/uid_stat/%s/tcp_snd" % (target, uid)).strip()
237 | # print rec, sen
238 | flow = float(rec) + float(sen)
239 | else:
240 | if flag == 1:
241 | # self.adbStartActivity(target, activity)
242 | pid = self.adbGetPid(target, packname)
243 | print pid
244 | lis = self.call_adb("-s %s shell cat /proc/%s/net/dev" % (target, pid)).strip().split()
245 | for k, v in enumerate(lis):
246 | if v == 'wlan0:':
247 | recindex = k + 1
248 | tranindex = k + 9
249 | flow = float(lis[recindex])+float(lis[tranindex])
250 | self.adbStopActivity(target, packname)
251 | break
252 | else:
253 | lis = self.call_adb("-s %s shell cat /proc/net/dev" % (target)).strip().split()
254 | for k, v in enumerate(lis):
255 | if v == 'wlan0:':
256 | recindex = k + 1
257 | tranindex = k + 9
258 | flow = float(lis[recindex]) + float(lis[tranindex])
259 | break
260 |
261 | return flow
262 |
263 |
264 | def adbGetPid(self, target, packname):
265 | if int(self.adbGetAndroidVersion(target).split('.')[0]) < 8:
266 | pid = self.call_adb("-s %s shell ps | findstr %s"%(target, packname)).rstrip().split("\n")
267 | if pid == ['']:
268 | print "this process doesn't exist"
269 | return None
270 | else:
271 | for item in pid:
272 | if item.split()[8] == packname:
273 | return item.split()[1]
274 | else:
275 | pid = self.call_adb("-s %s shell top -n 1 | findstr %s" % (target, packname)).strip().split()
276 | if pid == []:
277 | print "this process doesn't exist"
278 | return None
279 | else:
280 | return pid[0]
281 |
282 |
283 |
284 | def adbGetUid(self, target, packname):
285 | pid = self.adbGetPid(target, packname)
286 | lis = self.call_adb('-s %s shell cat /proc/%s/status' % (target, pid)).split()
287 | uid = 0
288 | for k, v in enumerate(lis):
289 | if v == 'Uid:':
290 | index = k + 1
291 | uid = lis[index]
292 | break
293 | return uid
294 |
295 | def adbGetAPPstartTime(self, target, activity):
296 | lis = self.call_adb('-s %s shell am start -W %s' % (target, activity))
297 | for k, v in enumerate(lis):
298 | if v == 'TotalTime:':
299 | index = k + 1
300 | time = lis[index]
301 | break
302 | return time
303 |
304 |
305 |
306 |
307 | if __name__ == '__main__':
308 | pass
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
--------------------------------------------------------------------------------
/lib/AppDevInfo.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: UTF-8 -*-
3 | import os,re
4 | from lib.AppAdbCom import AdbDebug
5 | ad = AdbDebug()
6 |
7 | class DeviceMsg(object):
8 |
9 | def GetDevModel(self, dev):
10 | result = {}
11 | result["release"] = ad.adbGetAndroidVersion(dev)# Android 系统,如anroid 4.0
12 | result["phone_name"] = ad.adbGetDeviceName(dev) # 手机名
13 | result["phone_model"] = ad.adbGetDeviceBrand(dev) # 手机品牌
14 | return result
15 |
16 | #获取手机内存总数
17 | def GetDevMemTotal(self, dev):
18 | list = ad.adbGetDevMem(dev).split()
19 | for k, v in enumerate(list):
20 | if str(v) == 'MemTotal:':
21 | return int(list[k+1])
22 |
23 | #获取手机处理器核数量
24 | def GetDevCpuCore(self, dev):
25 | resp = ad.adbGetDevCPU(dev)
26 | return str(len(re.findall("processor", resp)))
27 |
28 | #获取手机屏幕分辨率
29 | def GetDevPix(self, dev):
30 | resp = ad.adbGetScreenSize(dev).split()[2]
31 | return resp
32 |
33 | def GetDevMsg(self, dev):
34 | pix = self.GetDevPix(dev)
35 | men_total = self.GetDevMemTotal(dev)
36 | phone_msg = self.GetDevModel(dev)
37 | cpu_sum = self.GetDevCpuCore(dev)
38 | # print(dev + ":"+ pix,men_total,phone_msg,cpu_sum)
39 | return phone_msg, men_total, cpu_sum, pix
40 |
41 |
42 | if __name__ == "__main__":
43 | pass
44 |
45 |
--------------------------------------------------------------------------------
/lib/AppMonitor.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: UTF-8 -*-
3 | import os,subprocess,time,re,time
4 | import AppAdbCom
5 | from lib.AppOperatePick import OperatePick
6 | from PerConfig import AppPerCon
7 | from wsgiref.validate import validator
8 |
9 |
10 | PATH = lambda p: os.path.abspath(os.path.join(os.path.dirname(os.path.realpath('__file__')), p)) #os.path.realpath(path) 返回path的真实路径
11 | dev_list =[]
12 | ad = AppAdbCom.AdbDebug()
13 | pick = OperatePick()
14 | Config = AppPerCon()
15 |
16 | class AppMoni(object):
17 |
18 | # 判断传入的dev字符串是否是ip地址
19 | def IsIP(self, dev):
20 | if dev == '':
21 | return False
22 | index = dev.find(':')
23 | if index != -1:
24 | ip = dev[:index]
25 | addr = ip.split('.')
26 | if len(addr) != 4:
27 | return False
28 | for i in addr:
29 | if int(i) < 255 and int(i) >= 0:
30 | return True
31 | else:
32 | return False
33 |
34 |
35 | def get_device(self):
36 | rt = os.popen('adb devices').readlines() # os.popen()执行系统命令并返回执行后的结果
37 | n = len(rt) - 2
38 | print("当前已连接待测手机数为:" + str(n))
39 | for i in range(n):
40 | nPos = rt[i + 1].index("\t")
41 | dev = rt[i+1][:nPos]
42 | dev_list.append(dev)
43 | return dev_list
44 |
45 |
46 | def get_pid(self, target, pack):
47 | pid = ad.adbGetPid(target, pack)
48 | return pid
49 |
50 | def get_devSystemison(self,target):
51 | return ad.adbGetAndroidVersion(target)
52 |
53 | def get_battery(self, target):
54 | list = ad.adbGetBattery(target).split()
55 | for k,v in enumerate(list):
56 | if str(v) == "level:":
57 | battery = int(list[k+1])
58 | print("--------battery--------")
59 | if self.IsIP(target) == True:
60 | target = target.split(':')[0].replace(".", "")
61 | print type(battery)
62 | pick.writeInfo(battery, PATH(Config.info_path + target + "_battery.pickle"))
63 | else:
64 | pick.writeInfo(battery, PATH(Config.info_path + target + "_battery.pickle"))
65 | return battery
66 |
67 | def totalCpuTime(self, dev):
68 | user = nice = system = idle = iowait = irq = softirq = 0
69 | '''
70 | user 从系统启动开始累计到当前时刻,用户态的CPU时间(单位:jiffies) ,不包含 nice值为负进程。1jiffies=0.01秒
71 | nice 从系统启动开始累计到当前时刻,nice值为负的进程所占用的CPU时间(单位:jiffies)
72 | system 从系统启动开始累计到当前时刻,核心时间(单位:jiffies)
73 | idle 从系统启动开始累计到当前时刻,除硬盘IO等待时间以外其它等待时间(单位:jiffies)
74 | iowait 从系统启动开始累计到当前时刻,硬盘IO等待时间(单位:jiffies) ,
75 | irq 从系统启动开始累计到当前时刻,硬中断时间(单位:jiffies)
76 | softirq 从系统启动开始累计到当前时刻,软中断时间(单位:jiffies)
77 | '''
78 | res = ad.adbGetCpuTime(dev).split()
79 | try:
80 | for info in res:
81 | if info == "cpu":
82 | user = res[1]
83 | nice = res[2]
84 | system = res[3]
85 | idle = res[4]
86 | iowait = res[5]
87 | irq = res[6]
88 | softirq = res[7]
89 | result = int(user) + int(nice) + int(system) + int(idle) + int(iowait) + int(irq) + int(softirq)
90 | # print("totalCpuTime=" + str(result))
91 | return result
92 | except:
93 | return 0
94 |
95 | def pidCpuJiff(self, target, pid):
96 | '''
97 | utime 该任务在用户态运行的时间,单位为jiffies
98 | stime 该任务在核心态运行的时间,单位为jiffies
99 | cutime 累计的该任务的所有的waited-for进程曾经在用户态运行的时间,单位为jiffies
100 | cstime= 累计的该任务的所有的waited-for进程曾经在核心态运行的时间,单位为jiffies
101 | '''
102 | utime = stime = cutime = cstime = 0
103 | try:
104 | res = ad.adbGetPidJiff(target, pid).split()
105 | utime = res[13]
106 | stime = res[14]
107 | cutime = res[15]
108 | cstime = res[16]
109 | result = int(utime) + int(stime) + int(cutime) + int(cstime)
110 | except:
111 | result = 0
112 | return result
113 |
114 |
115 | '''
116 | 通过jiff来进行CPU计算
117 | '''
118 |
119 | def cpu_jiffrate(self, dev, packname):
120 | pid = self.get_pid(dev, packname)
121 | processCpuTime1 = self.pidCpuJiff(dev, pid)
122 | totalCpuTime1 = self.totalCpuTime(dev)
123 | time.sleep(1)
124 | processCpuTime2 = self.pidCpuJiff(dev, pid)
125 | totalCpuTime2 = self.totalCpuTime(dev)
126 | processCpuTime3 = processCpuTime2 - processCpuTime1
127 | totalCpuTime3 = (totalCpuTime2 - totalCpuTime1)
128 | cpu = 100 * (processCpuTime3) / (totalCpuTime3)
129 | return cpu
130 |
131 | '''
132 | 计算某进程的cpu使用率 top方式
133 | dev : 设备号
134 | packname: 应用包名
135 | flag : # 0: 空闲状态
136 | # 1:中等压力
137 | # 2:满压力
138 | '''
139 | def pid_cpuRate(self, dev, packname, flag):
140 | pid = self.get_pid(dev, packname)
141 | if int(self.get_devSystemison(dev).split('.')[0])<8:
142 | reslist = ad.call_adb("-s %s shell top -s cpu -n 1 | findstr %s" % (dev, pid)).split()
143 | #print reslist
144 | ratelist = list(reslist[4])
145 | strRate = ''
146 | for i in range(len(ratelist) - 1):
147 | strRate += ratelist[i]
148 | rate = int(strRate)
149 | else:
150 | rate = self.cpu_jiffrate(dev, packname)
151 | print("--------设备:%s cpurate--------") % dev
152 | if rate >= 0 and flag == 0:
153 | if self.IsIP(dev) == True:
154 | devIP = dev.split(':')[0].replace(".", "")
155 | pick.writeInfo(rate, PATH(Config.info_path + devIP + "_"+ Config.package_name + "_" + "Free_cpu.pickle"))
156 | pick.writeInfo(time.strftime("%H:%M:%S", time.localtime(time.time())),
157 | PATH(Config.info_path + devIP + "_" + Config.package_name + "_" + "Free_cpu.pickle"))
158 | else:
159 | pick.writeInfo(rate, PATH(Config.info_path + dev + "_"+ Config.package_name + "_" + "Free_cpu.pickle"))
160 | pick.writeInfo(time.strftime("%H:%M:%S", time.localtime(time.time())),
161 | PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Free_cpu.pickle"))
162 | elif rate >= 0 and flag == 1:
163 | if self.IsIP(dev) == True:
164 | devIP = dev.split(':')[0].replace(".", "")
165 | pick.writeInfo(rate, PATH(Config.info_path + devIP + "_"+ Config.package_name + "_" + "Medium_cpu.pickle"))
166 | pick.writeInfo(time.strftime("%H:%M:%S", time.localtime(time.time())),
167 | PATH(Config.info_path + devIP + "_" + Config.package_name + "_" + "Medium_cpu.pickle"))
168 | else:
169 | pick.writeInfo(rate, PATH(Config.info_path + dev + "_"+ Config.package_name + "_" + "Medium_cpu.pickle"))
170 | pick.writeInfo(time.strftime("%H:%M:%S", time.localtime(time.time())),
171 | PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Medium_cpu.pickle"))
172 | elif rate >= 0 and flag == 2:
173 | if self.IsIP(dev) == True:
174 | devIP = dev.split(':')[0].replace(".", "")
175 | pick.writeInfo(rate, PATH(Config.info_path + devIP + "_"+ Config.package_name + "_" + "Full_cpu.pickle"))
176 | pick.writeInfo(time.strftime("%H:%M:%S", time.localtime(time.time())),
177 | PATH(Config.info_path + devIP + "_" + Config.package_name + "_" + "Full_cpu.pickle"))
178 | else:
179 | pick.writeInfo(rate, PATH(Config.info_path + dev + "_"+ Config.package_name + "_" + "Full_cpu.pickle"))
180 | pick.writeInfo(time.strftime("%H:%M:%S", time.localtime(time.time())),
181 | PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Full_cpu.pickle"))
182 | elif rate >= 0 and flag == 3:
183 | if self.IsIP(dev) == True:
184 | devIP = dev.split(':')[0].replace(".", "")
185 | pick.writeInfo(rate, PATH(Config.info_path + devIP + "_"+ Config.package_name + "_" + "Manual_cpu.pickle"))
186 | pick.writeInfo(time.strftime("%H:%M:%S", time.localtime(time.time())),
187 | PATH(Config.info_path + devIP + "_" + Config.package_name + "_" + "Manual_cpu.pickle"))
188 | else:
189 | pick.writeInfo(rate, PATH(Config.info_path + dev + "_"+ Config.package_name + "_" + "Manual_cpu.pickle"))
190 | pick.writeInfo(time.strftime("%H:%M:%S", time.localtime(time.time())),
191 | PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Manual_cpu.pickle"))
192 | return rate
193 |
194 | #获得CPU进程时间片
195 | def pid_Jiff(self, dev, pid):
196 | processCpuTime1 = self.pidCpuJiff(dev, pid)
197 | time.sleep(1)
198 | processCpuTime2 = self.pidCpuJiff(dev, pid)
199 | processCpuTime3 = processCpuTime2 - processCpuTime1
200 | jiff = processCpuTime3
201 | print("--------jiff--------")
202 | if jiff >= 0:
203 | if self.IsIP(dev) == True:
204 | devIP = dev.split(':')[0].replace(".", "")
205 | pick.writeInfo(jiff, PATH(Config.info_path + devIP + "_"+ Config.package_name + "_" + "_jiff.pickle"))
206 | else:
207 | pick.writeInfo(jiff, PATH(Config.info_path + dev + "_"+ Config.package_name + "_" + "_jiff.pickle"))
208 | return jiff
209 |
210 |
211 | '''
212 | 获得指定应用内存信息
213 | # 0: 空闲状态
214 | # 1:中等压力
215 | # 2:满压力
216 | '''
217 | def pid_mem(self, dev, pkg_name, flag):
218 | lis = ad.adbGetDevPidMem(dev, pkg_name).split()
219 | #print lis
220 | for i in range(len(lis)):
221 | if lis[i] == "TOTAL":
222 | data = lis[i+1]
223 | break
224 | mem = int(data)
225 | print("--------设备:%s mem--------") % dev
226 | if mem >= 0 and flag == 0:
227 | if self.IsIP(dev) == True:
228 | devIP = dev.split(':')[0].replace(".", "")
229 | pick.writeInfo(mem, PATH(Config.info_path + devIP + "_"+ Config.package_name + "_" + "Free_mem.pickle"))
230 | pick.writeInfo(time.strftime("%H:%M:%S", time.localtime(time.time())),
231 | PATH(Config.info_path + devIP + "_" + Config.package_name + "_" + "Free_mem.pickle"))
232 | else:
233 | pick.writeInfo(mem, PATH(Config.info_path + dev + "_"+ Config.package_name + "_" + "Free_mem.pickle"))
234 | pick.writeInfo(time.strftime("%H:%M:%S", time.localtime(time.time())),
235 | PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Free_mem.pickle"))
236 |
237 | elif mem >= 0 and flag == 1:
238 | if self.IsIP(dev) == True:
239 | devIP = dev.split(':')[0].replace(".", "")
240 | pick.writeInfo(mem, PATH(Config.info_path + devIP + "_"+ Config.package_name + "_" + "Medium_mem.pickle"))
241 | pick.writeInfo(time.strftime("%H:%M:%S", time.localtime(time.time())),
242 | PATH(Config.info_path + devIP + "_" + Config.package_name + "_" + "Medium_mem.pickle"))
243 | else:
244 | pick.writeInfo(mem, PATH(Config.info_path + dev + "_"+ Config.package_name + "_" + "Medium_mem.pickle"))
245 | pick.writeInfo(time.strftime("%H:%M:%S", time.localtime(time.time())),
246 | PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Medium_mem.pickle"))
247 | elif mem >= 0 and flag == 2:
248 | if self.IsIP(dev) == True:
249 | devIP = dev.split(':')[0].replace(".", "")
250 | pick.writeInfo(mem, PATH(Config.info_path + devIP + "_"+ Config.package_name + "_" + "Full_mem.pickle"))
251 | pick.writeInfo(time.strftime("%H:%M:%S", time.localtime(time.time())),
252 | PATH(Config.info_path + devIP + "_" + Config.package_name + "_" + "Full_mem.pickle"))
253 | else:
254 | pick.writeInfo(mem, PATH(Config.info_path + dev + "_"+ Config.package_name + "_" + "Full_mem.pickle"))
255 | pick.writeInfo(time.strftime("%H:%M:%S", time.localtime(time.time())),
256 | PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Full_mem.pickle"))
257 | elif mem >= 0 and flag == 3:
258 | if self.IsIP(dev) == True:
259 | devIP = dev.split(':')[0].replace(".", "")
260 | pick.writeInfo(mem, PATH(Config.info_path + devIP + "_"+ Config.package_name + "_" + "Manual_mem.pickle"))
261 | pick.writeInfo(time.strftime("%H:%M:%S", time.localtime(time.time())),
262 | PATH(Config.info_path + devIP + "_" + Config.package_name + "_" + "Manual_mem.pickle"))
263 | else:
264 | pick.writeInfo(mem, PATH(Config.info_path + dev + "_"+ Config.package_name + "_" + "Manual_mem.pickle"))
265 | pick.writeInfo(time.strftime("%H:%M:%S", time.localtime(time.time())),
266 | PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Manual_mem.pickle"))
267 | return mem
268 |
269 |
270 | # 获得指定应用FPS信息
271 |
272 | def pid_fps(self, dev, pkg_name, flag):
273 | results = ad.adbGetPidfps(dev, pkg_name)
274 | # print results
275 | frames = [x for x in results.split('\n')]
276 | jank_count = 0
277 | vsync_overtime = 0
278 | render_time = 0
279 | try:
280 | for k,v in enumerate(frames):
281 | if v == '\tDraw\tPrepare\tProcess\tExecute' or v == '\tDraw\tProcess\tExecute\r':
282 | indexstart = k+1
283 | elif v == 'View hierarchy:' or v == 'View hierarchy:\r':
284 | indexend = k-1
285 | fra = frames[indexstart:indexend]
286 | frame_count = len(fra)
287 | for frame in fra:
288 | time_block = re.split(r'\s+', frame.strip())
289 | for k, v in enumerate(frames):
290 | if v == '\tDraw\tProcess\tExecute\r':
291 | render_time = float(time_block[0]) + float(time_block[1]) + float(time_block[2])
292 | elif v == '\tDraw\tPrepare\tProcess\tExecute':
293 | render_time = float(time_block[0]) + float(time_block[1]) + float(time_block[2]) + float(time_block[3])
294 | '''
295 | 当渲染时间大于16.67,按照垂直同步机制,该帧就已经渲染超时
296 | 那么,如果它正好是16.67的整数倍,比如66.68,则它花费了4个垂直同步脉冲,减去本身需要一个,则超时3个
297 | 如果它不是16.67的整数倍,比如67,那么它花费的垂直同步脉冲应向上取整,即5个,减去本身需要一个,即超时4个,可直接算向下取整
298 |
299 | 最后的计算方法思路:
300 | 执行一次命令,总共收集到了m帧(理想情况下m=128),但是这m帧里面有些帧渲染超过了16.67毫秒,算一次jank,一旦jank,
301 | 需要用掉额外的垂直同步脉冲。其他的就算没有超过16.67,也按一个脉冲时间来算(理想情况下,一个脉冲就可以渲染完一帧)
302 |
303 | 所以FPS的算法可以变为:
304 | m / (m + 额外的垂直同步脉冲) * 60
305 | '''
306 | if render_time > 16.67:
307 | jank_count += 1
308 | if render_time % 16.67 == 0:
309 | vsync_overtime += int(render_time / 16.67) - 1
310 | else:
311 | vsync_overtime += int(render_time / 16.67)
312 | print("-----fps------")
313 | if frame_count == 0:
314 | _fps = 60
315 | else:
316 | _fps = int(frame_count * 60 / (frame_count + vsync_overtime))
317 | if flag == 1:
318 | if self.IsIP(dev) == True:
319 | devIP = dev.split(':')[0].replace(".", "")
320 | pick.writeInfo(_fps, PATH(Config.info_path + devIP + "_"+ Config.package_name + "_" + "Medium_fps.pickle"))
321 | pick.writeInfo(time.strftime("%H:%M:%S", time.localtime(time.time())),
322 | PATH(Config.info_path + devIP + "_" + Config.package_name + "_" + "Medium_fps.pickle"))
323 | else:
324 | pick.writeInfo(_fps, PATH(Config.info_path + dev + "_"+ Config.package_name + "_" + "Medium_fps.pickle"))
325 | pick.writeInfo(time.strftime("%H:%M:%S", time.localtime(time.time())),
326 | PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Medium_fps.pickle"))
327 |
328 | elif flag == 2:
329 | if self.IsIP(dev) == True:
330 | devIP = dev.split(':')[0].replace(".", "")
331 | pick.writeInfo(_fps, PATH(Config.info_path + devIP + "_"+ Config.package_name + "_" + "Full_fps.pickle"))
332 | pick.writeInfo(time.strftime("%H:%M:%S", time.localtime(time.time())),
333 | PATH(Config.info_path + devIP + "_" + Config.package_name + "_" + "Full_fps.pickle"))
334 | else:
335 | pick.writeInfo(_fps, PATH(Config.info_path + dev + "_"+ Config.package_name + "_" + "Full_fps.pickle"))
336 | pick.writeInfo(time.strftime("%H:%M:%S", time.localtime(time.time())),
337 | PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Full_fps.pickle"))
338 | elif flag == 3:
339 | if self.IsIP(dev) == True:
340 | devIP = dev.split(':')[0].replace(".", "")
341 | pick.writeInfo(_fps, PATH(Config.info_path + devIP + "_"+ Config.package_name + "_" + "Manual_fps.pickle"))
342 | pick.writeInfo(time.strftime("%H:%M:%S", time.localtime(time.time())),
343 | PATH(Config.info_path + devIP + "_" + Config.package_name + "_" + "Manual_fps.pickle"))
344 | else:
345 | pick.writeInfo(_fps, PATH(Config.info_path + dev + "_"+ Config.package_name + "_" + "Manual_fps.pickle"))
346 | pick.writeInfo(time.strftime("%H:%M:%S", time.localtime(time.time())),
347 | PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Manual_fps.pickle"))
348 | return _fps
349 | except Exception as e:
350 | print "请打开开发者模式中的GPU显示"
351 |
352 |
353 | # 获得指定应用上下行流量信息
354 | def flow(self, dev, packname, activity):
355 | ad.adbStopActivity(dev, packname)
356 | flow1 = self.pid_flowSingle(dev, packname, 0)
357 | time.sleep(1)
358 | ad.adbStartActivity(dev, activity)
359 | time.sleep(15)
360 | flow2 = self.pid_flowSingle(dev, packname, 1)
361 | flow = (flow2 - flow1) / 1024
362 | if self.IsIP(dev) == True:
363 | devIP = dev.split(':')[0].replace(".", "")
364 | pick.writeInfo(flow, PATH(Config.info_path + devIP + "_"+ Config.package_name + "_" + "first_flow.pickle"))
365 | else:
366 | pick.writeInfo(flow, PATH(Config.info_path + dev + "_"+ Config.package_name + "_" + "first_flow.pickle"))
367 | return flow
368 |
369 | def pid_flowSingle(self, dev, packname, flag):
370 | flow = ad.adbGetPidflow(dev, packname, flag)
371 | return flow
372 |
373 | def pid_startTime(self, dev, packname):
374 | time = ad.adbGetPidflow(dev, packname)
375 | return int(time)
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 | if __name__ == '__main__':
387 | pass
--------------------------------------------------------------------------------
/lib/AppOperateFile.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: UTF-8 -*-
3 | import os
4 |
5 | '''
6 | 操作文件
7 | '''
8 | class OperateFile(object):
9 | def __init__(self, file, method='w+'):
10 | self.file = file
11 | self.method = method
12 | self.fileHandle = None
13 |
14 |
15 | def mkdir_file(self):
16 | if not os.path.isfile(self.file):
17 | f = open(self.file, self.method)
18 | f.close()
19 | print("创建文件成功")
20 | else:
21 | print("文件已经存在")
22 |
23 |
24 | def remove_file(self):
25 | if os.path.isfile(self.file):
26 | os.remove(self.file)
27 | print("删除文件成功")
28 | else:
29 | print("文件不存在")
--------------------------------------------------------------------------------
/lib/AppOperatePick.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: UTF-8 -*-
3 | import os
4 | import pickle
5 |
6 | '''
7 | 操作文件
8 | '''
9 | class OperatePick(object):
10 |
11 | def readInfo(self, path):
12 | data=[]
13 | with open(path, 'rb') as f:
14 | try:
15 | data = pickle.load(f)
16 | # print(data)
17 | except EOFError:
18 | data = []
19 | print("读取文件错误,文件内容为空")
20 | print("------read-------")
21 | print data
22 | return data
23 |
24 | def writeSum(self, init, data=None, path="data.pickle"):
25 | if init == 0:
26 | result = data
27 | else:
28 | _read = self.readInfo(path)
29 | result = _read - _read
30 |
31 | with open(path, 'wb') as f:
32 | print("------writeSum-------")
33 | print "Sum:%s" % result
34 | pickle.dump(result, f)
35 |
36 | def readSum(self, path):
37 | data = {}
38 | with open(path, 'rb') as f:
39 | try:
40 | data = pickle.load(f)
41 | except EOFError:
42 | data = {}
43 | print("读取文件错误,文件内容为空")
44 | print("------read-------")
45 | return data
46 |
47 | def writeInfo(self, data, path):
48 | _read = self.readInfo(path)
49 | result=[]
50 | if _read:
51 | _read.append(data)
52 | result = _read
53 | else:
54 | result.append(data)
55 | with open(path, 'wb') as f:
56 | print("------writeInfo-------")
57 | print result
58 | pickle.dump(result, f)
59 |
--------------------------------------------------------------------------------
/lib/AppReport.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: UTF-8 -*-
3 | import os,subprocess,time,re,time
4 | from pyecharts import Bar, Line, Scatter, EffectScatter, Grid, Page, Scatter3D, Overlap
5 | from PerConfig import AppPerCon
6 | from lib.AppAdbCom import AdbDebug
7 | from lib.AppDevInfo import DeviceMsg
8 | from lib.AppMonitor import AppMoni
9 | from lib.AppOperateFile import OperateFile
10 | from lib.AppOperatePick import OperatePick
11 |
12 | PATH = lambda p: os.path.abspath(os.path.join(os.path.dirname(os.path.realpath('__file__')), p)) #os.path.realpath(path) 返回path的真实路径
13 | pick = OperatePick()
14 |
15 | class Report(object):
16 | def __init__(self, dev, reportName, flag ):
17 | self.reportName = reportName
18 | self.dev = dev
19 | self.pack = AppPerCon.package_name
20 | self.flag = flag
21 |
22 | def createComparReport(self):
23 | pass
24 |
25 | def createReport(self, dev):
26 | lisMem = pick.readInfo(AppPerCon.info_path + self.dev + '_' + self.pack + '_' + self.flag + "_mem.pickle")
27 | lisCpu = pick.readInfo(AppPerCon.info_path + self.dev + '_' + self.pack + '_' + self.flag + "_cpu.pickle")
28 | lisFps = pick.readInfo(AppPerCon.info_path + self.dev + '_' + self.pack + '_' + self.flag + "_fps.pickle")
29 | lisDevinfo = pick.readInfo(AppPerCon.info_path + "info.pickle")
30 |
31 |
32 | pix = lisDevinfo[0][dev]['header']['pix']
33 | net = lisDevinfo[0][dev]['header']['net']
34 | name = lisDevinfo[0][dev]['header']['phone_name']
35 | rom = lisDevinfo[0][dev]['header']['rom']
36 |
37 |
38 | devinfo = "设备信息-分辨率:" + pix + "\\"\
39 | +"网络:" + net + "\\"\
40 | +"设备名:"+ name + "\\"\
41 | +"内存容量:"+ str(rom)+"MB"
42 |
43 |
44 |
45 |
46 |
47 |
48 | v1 = [i for i in lisCpu if type(i) == str]
49 | v2 = [i for i in lisCpu if type(i) != str]
50 | v3 = [i for i in lisMem if type(i) == str]
51 | v4 = [i for i in lisMem if type(i) != str]
52 | v5 = [i for i in lisFps if type(i) == str]
53 | v6 = [i for i in lisFps if type(i) != str]
54 |
55 |
56 |
57 | page = Page(self.reportName.decode('utf-8'))
58 |
59 | attr = v1
60 | bar = Bar()
61 | bar.add("ROKI_bar", attr, v2)
62 | line = Line(self.reportName +"-"+"CPU占用", devinfo ,width=1200, height=400)
63 | line.add("ROKI_line", attr, v2, is_stack=True, is_label_show=True,
64 | is_smooth=False ,is_more_utils =True,is_datazoom_show=False, yaxis_formatter="%",
65 | mark_point=["max", "min"], mark_line=["average"])
66 |
67 | overlap = Overlap(self.reportName +"-"+"CPU占用", width=1200, height=400)
68 | overlap.add(line)
69 | overlap.add(bar)
70 | page.add(overlap)
71 |
72 | attr1 = v3
73 | line1 = Line(self.reportName + "-" + "MEM消耗", width=1200, height=400)
74 | line1.add("ROKI_line", attr1, v4, is_stack=True, is_label_show=True, is_smooth=False,is_more_utils =True, is_datazoom_show=False,
75 | yaxis_formatter="MB", mark_point=["max", "min"], mark_line=["average"])
76 | bar1 = Bar()
77 | bar1.add("ROKI_bar", attr1, v4)
78 | overlap1 = Overlap(width=1200, height=400)
79 | overlap1.add(line1)
80 | overlap1.add(bar1)
81 | page.append(overlap1)
82 |
83 | attr2 = v5
84 | line2 = Line(self.reportName + "-" + "FPS帧率", width=1200, height=400)
85 | line2.add("ROKI_line", attr2, v6, is_stack=True, is_label_show=True, is_smooth=False,is_more_utils =True, is_datazoom_show=False,
86 | yaxis_formatter="fps", mark_point=["max", "min"], mark_line=["average"])
87 | bar2 = Bar()
88 | bar2.add("ROKI_bar", attr2, v6)
89 | overlap2 = Overlap(width=1200, height=400)
90 | overlap2.add(line2)
91 | overlap2.add(bar2)
92 | page.append(overlap2)
93 |
94 | page.render(AppPerCon.report_path + self.dev +"_"+ self.pack + "_"+self.flag+"_"+"report.html")
95 |
96 | if __name__ == '__main__':
97 | rep= Report("APU0215C08002952","Alink V2.6.17 性能测试报告", "Medium")
98 | rep.createReport("APU0215C08002952")
99 |
--------------------------------------------------------------------------------
/lib/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: UTF-8 -*-
--------------------------------------------------------------------------------
/monkey_stop.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 | # coding: utf-8
3 | import subprocess
4 | from Base import BaseMonitor
5 | import time
6 | import os
7 |
8 | def stop_monkey(dev):
9 | monkey_name = "com.android.commands.monkey"
10 | pid = subprocess.Popen("adb -s " + dev + " shell ps | findstr " + monkey_name, shell=True, stdout=subprocess.PIPE,stderr=subprocess.PIPE).stdout.readlines()
11 | if pid =="":
12 | print("No monkey running in %s" % dev)
13 | else:
14 | for item in pid:
15 | if item.split()[8].decode() == monkey_name:
16 | monkey_pid = item.split()[1].decode()
17 | cmd_monkey = "adb -s " + dev + " shell kill %s" % (monkey_pid)
18 | os.popen(cmd_monkey)
19 | print("Monkey in %s was killed" % dev)
20 | time.sleep(2)
21 |
22 | def reboot(dev):
23 | cmd_reboot = "adb -s " + dev + " reboot"
24 | os.popen(cmd_reboot)
25 |
26 | if __name__ == '__main__':
27 | device_list = BaseMonitor.get_devices()
28 | for dev in device_list:
29 | stop_monkey(dev)
30 | #reboot(dev,dev_model) #如需要重启设备,删除注释即可
--------------------------------------------------------------------------------
/report.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtmaxzhu/AppPerformance/0c90e0e1aba23ea03db3062780fd3266046773aa/report.png
--------------------------------------------------------------------------------
/report/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: UTF-8 -*-
--------------------------------------------------------------------------------
/testCase/ManualTest.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: UTF-8 -*-
3 | import os,shutil
4 | import threading
5 | import time,datetime,subprocess
6 |
7 | from PerConfig import AppPerCon
8 | from lib.AppAdbCom import AdbDebug
9 | from lib.AppDevInfo import DeviceMsg
10 | from lib.AppMonitor import AppMoni
11 | from lib.AppOperateFile import OperateFile
12 | from lib.AppOperatePick import OperatePick
13 |
14 | PATH = lambda p: os.path.abspath(os.path.join(os.path.dirname(os.path.realpath('__file__')), p)) #os.path.realpath(path) 返回path的真实路径
15 |
16 | ad = AdbDebug()
17 | apm = AppMoni()
18 | devMs = DeviceMsg()
19 | pick = OperatePick()
20 | Config = AppPerCon()
21 |
22 | #全局变量
23 | MemTestFlag = 0
24 | monkey_log=''
25 | path_log=''
26 |
27 |
28 |
29 | # 手机信息
30 | def get_phone(dev):
31 | phone_info = devMs.GetDevMsg(dev)
32 | # print phone_info
33 | app = {}
34 | app["phone_name"] = phone_info[0]["phone_name"] + "_" + phone_info[0]["phone_model"] + "_" + phone_info[0]["release"]
35 | app["rom"] = phone_info[1]
36 | app["kel"] = phone_info[2]
37 | app["pix"] = phone_info[3]
38 | return app
39 |
40 | def Create_pickle(dev, app, data):
41 | print("创建持久性文件...")
42 | if apm.IsIP(dev) == True:
43 | devIP = dev.split(':')[0].replace(".","")
44 | Manualmen = PATH(Config.info_path + devIP + "_" + Config.package_name + "_" + "Manual_mem.pickle")
45 | Manualcpu = PATH(Config.info_path + devIP + "_" + Config.package_name + "_" + "Manual_cpu.pickle")
46 | Manualjiff = PATH(Config.info_path + devIP + "_" + Config.package_name + "_" + "Manual_jiff.pickle")
47 | Manualfps = PATH(Config.info_path + devIP + "_" + Config.package_name + "_" + "Manual_fps.pickle")
48 |
49 | else:
50 | Manualmen = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Manual_mem.pickle")
51 | Manualcpu = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Manual_cpu.pickle")
52 | Manualjiff = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Manual_jiff.pickle")
53 | Manualfps = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Manual_fps.pickle")
54 |
55 | # time.sleep(2)
56 | # app[dev] = {"freemen": freemen, "medimen": medimen, "fullmen": fullmen,
57 | # "freecpu": freecpu, "medicpu": medicpu, "fullcpu": fullcpu,
58 | # "header": get_phone(dev)}
59 | OperateFile(Manualmen).mkdir_file()
60 | OperateFile(Manualcpu).mkdir_file()
61 | OperateFile(Manualjiff).mkdir_file()
62 | OperateFile(Manualfps).mkdir_file()
63 | OperateFile(PATH(Config.info_path + "sumInfo.pickle")).mkdir_file() # 用于记录是否已经测试完毕,里面存的是一个整数
64 | OperateFile(PATH(Config.info_path + "info.pickle")).mkdir_file() # 用于记录统计结果的信息,是[{}]的形式
65 | pick.writeSum(0, data, PATH(Config.info_path + "sumInfo.pickle")) # 初始化记录当前真实连接的设备数
66 |
67 | #log生成函数
68 | def logProcess(dev, runtime):
69 | # logcat日志
70 | logcat_log = path_log + "\\" + runtime + "logcat.log"
71 | cmd_logcat = "-s " + dev + " logcat -d > %s" % (logcat_log)
72 | ad.call_adb(cmd_logcat)
73 | print 'logcat 完成'
74 |
75 | # "导出traces文件"
76 | traces_log = path_log + "\\" + runtime + "traces.log"
77 | cmd_traces = "-s " + dev + " shell cat /data/anr/traces.txt > %s" % (traces_log)
78 | ad.call_adb(cmd_traces)
79 | print 'traces_log 完成'
80 |
81 | def start(dev):
82 | rt = os.popen('adb devices').readlines() # os.popen()执行系统命令并返回执行后的结果
83 | num = len(rt) - 2
84 | print(num)
85 | app = {}
86 | Create_pickle(dev, app, num)
87 | signal = raw_input("现在是手动测试部分,是否要开始你的测试,请输入(y or n): ")
88 | if signal == 'y' or 'Y':
89 | print("测试即将开始,请打开需要测试的app并准备执行您的操作....")
90 | time.sleep(5)
91 | run_time = time.strftime("%Y-%m-%d_%H%M%S", time.localtime(time.time()))
92 | logProcess(dev, run_time)
93 | while True:
94 | try:
95 | time.sleep(1) # 每1秒采集一次
96 | print("----------------数据采集-----------------")
97 | apm.pid_mem(dev, Config.package_name, 3)
98 | apm.pid_cpuRate(dev, Config.package_name, 3)
99 | #fps 测试需要打开开发者模式GPU模式
100 | apm.pid_fps(dev, Config.package_name, 3)
101 | except:
102 | break
103 |
104 | elif signal == 'n':
105 | print('用户主动放弃测试,测试结束!')
106 | else:
107 | print("测试结束,输入非法,请重新输入y or n!")
108 |
109 | #启动多线程
110 | class MonkeyTestThread(threading.Thread):
111 | def __init__(self, dev):
112 | threading.Thread.__init__(self)
113 | self.dev = dev
114 | self.thread_stop = False
115 |
116 | def run(self):
117 | time.sleep(2)
118 | start(self.dev)
119 |
120 |
121 |
122 | def create_threads_monkey(device_list):
123 | Thread_instances = []
124 | if device_list != []:
125 | for id_instance in device_list:
126 | dev = id_instance
127 | testInstance = MonkeyTestThread(dev)
128 | Thread_instances.append(testInstance)
129 | for instance in Thread_instances:
130 | instance.start()
131 |
132 |
133 | if __name__ == '__main__':
134 | device_dir = os.path.exists(AppPerCon.info_path)
135 | if device_dir:
136 | print ("持久性目录info已存在,继续执行测试!")
137 | else:
138 | #os.mkdir(AppPerformanceConfig.info_path) # 创建持久性目录,需要在文件存在的情况下创建二级目录
139 | os.makedirs(AppPerCon.info_path) # 使用makedirs可以在文件夹不存在的情况下直接创建
140 | device_list = apm.get_device()
141 | if ad.checkDevices():
142 | print("设备存在")
143 | create_threads_monkey(device_list)
144 | else:
145 | print("设备不存在")
146 |
147 |
148 |
--------------------------------------------------------------------------------
/testCase/MonkeyTest.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: UTF-8 -*-
3 | import os,shutil
4 | import threading
5 | import time,datetime,subprocess
6 |
7 | from PerConfig import AppPerCon
8 | from lib.AppAdbCom import AdbDebug
9 | from lib.AppDevInfo import DeviceMsg
10 | from lib.AppMonitor import AppMoni
11 | from lib.AppOperateFile import OperateFile
12 | from lib.AppOperatePick import OperatePick
13 | from lib.AppReport import Report
14 |
15 | PATH = lambda p: os.path.abspath(os.path.join(os.path.dirname(os.path.realpath('__file__')), p)) #os.path.realpath(path) 返回path的真实路径
16 |
17 | ad = AdbDebug()
18 | apm = AppMoni()
19 | devMs = DeviceMsg()
20 | pick = OperatePick()
21 | Config = AppPerCon()
22 |
23 | #全局变量
24 | MemTestFlag = 0
25 | monkey_log=''
26 | path_log=''
27 |
28 |
29 |
30 | # 手机信息
31 | def get_phone(dev):
32 | phone_info = devMs.GetDevMsg(dev)
33 | # print phone_info
34 | app = {}
35 | app["phone_name"] = phone_info[0]["phone_name"] + "_" + phone_info[0]["phone_model"] + "_" + phone_info[0]["release"]
36 | app["rom"] = phone_info[1]
37 | app["kel"] = phone_info[2]
38 | app["pix"] = phone_info[3]
39 | return app
40 |
41 | def Create_pickle(dev, data):
42 | print("创建持久性文件...")
43 | if apm.IsIP(dev) == True:
44 | devIP = dev.split(':')[0].replace(".","")
45 | freemen = PATH(Config.info_path + devIP + "_" + Config.package_name + "_" + "Free_mem.pickle")#空闲状态
46 | medimen = PATH(Config.info_path + devIP + "_" + Config.package_name + "_" + "Medium_mem.pickle")#中等压力
47 | fullmen = PATH(Config.info_path + devIP + "_" + Config.package_name + "_" + "Full_mem.pickle")#满压力
48 | freecpu = PATH(Config.info_path + devIP + "_" + Config.package_name + "_" + "Free_cpu.pickle")#空闲状态
49 | medicpu = PATH(Config.info_path + devIP + "_" + Config.package_name + "_" + "Medium_cpu.pickle")#中等压力
50 | fullcpu = PATH(Config.info_path + devIP + "_" + Config.package_name + "_" + "Full_cpu.pickle")#满压力
51 | freejiff = PATH(Config.info_path + devIP + "_" + Config.package_name + "_" + "Free_jiff.pickle")#空闲状态
52 | medijiff = PATH(Config.info_path + devIP + "_" + Config.package_name + "_" + "Medium_jiff.pickle")#中等压力
53 | fulljiff = PATH(Config.info_path + devIP + "_" + Config.package_name + "_" + "Full_jiff.pickle")#满压力
54 | medifps = PATH(Config.info_path + devIP + "_" + Config.package_name + "_" + "Medium_fps.pickle")#中等压力
55 | fullfps = PATH(Config.info_path + devIP + "_" + Config.package_name + "_" + "Full_fps.pickle")#满压力
56 | '''
57 | freemenTime = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Free_memTime.pickle")#空闲状态测试采样时间记录
58 | medimenTime = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Medium_memTime.pickle")
59 | fullmenTime = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Full_memTime.pickle")
60 | freecpuTime = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Free_cpuTime.pickle")
61 | medicpuTime = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Medium_cpuTime.pickle")
62 | fullcpuTime = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Full_cpuTime.pickle")
63 | freejiffTime = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Free_jiffTime.pickle")
64 | medijiffTime = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Medium_jiffTime.pickle")
65 | fulljiffTime = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Full_jiffTime.pickle")
66 | medifpsTime = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Medium_fpsTime.pickle")
67 | fullfpsTime = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Full_fpsTime.pickle")
68 | '''
69 | else:
70 | freemen = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Free_mem.pickle")#空闲状态
71 | medimen = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Medium_mem.pickle")#中等压力
72 | fullmen = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Full_mem.pickle")#满压力
73 | freecpu = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Free_cpu.pickle")#空闲状态
74 | medicpu = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Medium_cpu.pickle")#中等压力
75 | fullcpu = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Full_cpu.pickle")#满压力
76 | freejiff = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Free_jiff.pickle")#空闲状态
77 | medijiff = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Medium_jiff.pickle")#中等压力
78 | fulljiff = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Full_jiff.pickle")#满压力
79 | medifps = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Medium_fps.pickle")#中等压力
80 | fullfps = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Full_fps.pickle")#满压力
81 | '''
82 | freemenTime = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Free_memTime.pickle")#空闲状态测试采样时间记录
83 | medimenTime = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Medium_memTime.pickle")
84 | fullmenTime = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Full_memTime.pickle")
85 | freecpuTime = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Free_cpuTime.pickle")
86 | medicpuTime = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Medium_cpuTime.pickle")
87 | fullcpuTime = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Full_cpuTime.pickle")
88 | freejiffTime = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Free_jiffTime.pickle")
89 | medijiffTime = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Medium_jiffTime.pickle")
90 | fulljiffTime = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Full_jiffTime.pickle")
91 | medifpsTime = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Medium_fpsTime.pickle")
92 | fullfpsTime = PATH(Config.info_path + dev + "_" + Config.package_name + "_" + "Full_fpsTime.pickle")
93 | '''
94 |
95 | # time.sleep(2)
96 | OperateFile(freemen).mkdir_file()
97 | OperateFile(medimen).mkdir_file()
98 | OperateFile(fullmen).mkdir_file()
99 | OperateFile(freecpu).mkdir_file()
100 | OperateFile(medicpu).mkdir_file()
101 | OperateFile(fullcpu).mkdir_file()
102 | OperateFile(freejiff).mkdir_file()
103 | OperateFile(medijiff).mkdir_file()
104 | OperateFile(fulljiff).mkdir_file()
105 | OperateFile(medifps).mkdir_file()
106 | OperateFile(fullfps).mkdir_file()
107 | '''
108 | OperateFile(freemenTime).mkdir_file()
109 | OperateFile(medimenTime).mkdir_file()
110 | OperateFile(fullmenTime).mkdir_file()
111 | OperateFile(freecpuTime).mkdir_file()
112 | OperateFile(medicpuTime).mkdir_file()
113 | OperateFile(fullcpuTime).mkdir_file()
114 | OperateFile(freejiffTime).mkdir_file()
115 | OperateFile(medijiffTime).mkdir_file()
116 | OperateFile(fulljiffTime).mkdir_file()
117 | OperateFile(medifpsTime).mkdir_file()
118 | OperateFile(fullfpsTime).mkdir_file()
119 | '''
120 | OperateFile(PATH(Config.info_path + "sumInfo.pickle")).mkdir_file() # 用于记录是否已经测试完毕,里面存的是一个整数
121 | OperateFile(PATH(Config.info_path + "info.pickle")).mkdir_file() # 用于记录统计结果的信息,是[{}]的形式
122 | pick.writeSum(0, data, PATH(Config.info_path + "sumInfo.pickle")) # 初始化记录当前真实连接的设备数
123 |
124 | def unlockScreen(dev):
125 | cmd_openScreen = "-s %s shell input keyevent 224" % (dev)
126 | cmd_slide = "-s %s shell input swipe 300 500 1000 500" % (dev)
127 | ad.call_adb(cmd_openScreen) # 点亮屏幕
128 | time.sleep(0.5)
129 | ad.call_adb(cmd_slide) # 滑动解锁
130 |
131 | #log生成函数
132 | def logProcess(dev, runtime):
133 | # logcat日志
134 | logcat_log = path_log + "\\" + runtime + "logcat.log"
135 | cmd_logcat = "-s " + dev + " logcat -d > %s" % (logcat_log)
136 | ad.call_adb(cmd_logcat)
137 | print 'logcat 完成'
138 |
139 | # "导出traces文件"
140 | traces_log = path_log + "\\" + runtime + "traces.log"
141 | cmd_traces = "-s " + dev + " shell cat /data/anr/traces.txt > %s" % (traces_log)
142 | ad.call_adb(cmd_traces)
143 | print 'traces_log 完成'
144 |
145 |
146 | # monkey启动函数
147 | def monkeyStart(dev, runtime, flag):
148 | global path_log
149 | if apm.IsIP(dev) == True:
150 | devIP = dev.split(':')[0].replace(".", "")
151 | path_log = Config.log_location + '-' + devIP
152 | else:
153 | path_log = Config.log_location + '-' + dev
154 | device_dir = os.path.exists(path_log)
155 | if device_dir:
156 | print("log已存在,继续执行测试!")
157 | else:
158 | os.mkdir(path_log)
159 | if flag == 2:
160 | adb_monkey = "shell monkey -p %s -s %s %s" % (Config.package_name, Config.monkey_seed, Config.monkey_parameters_full)
161 | elif flag == 1:
162 | adb_monkey = "shell monkey -p %s -s %s %s" % (Config.package_name, Config.monkey_seed, Config.monkey_parameters_medi)
163 | global monkey_log
164 | monkey_log = path_log + "\\" + runtime + "monkey.log"
165 | cmd_monkey = "adb -s %s %s > %s" % (dev, adb_monkey, monkey_log)
166 | subprocess.Popen(cmd_monkey, shell=True)
167 |
168 |
169 | def mediMemTest(dev, app):
170 | print("--------------开始执行测试----------------")
171 | print("--------------设备:%s 场景2:中等压力下APP性能指标----------------") % dev
172 | ad.adbStopActivity(dev, Config.package_name)
173 | run_time = time.strftime("%Y-%m-%d_%H%M%S", time.localtime(time.time()))
174 | monkeyStart(dev, run_time, 1)
175 | logProcess(dev, run_time)#放在monkeystart之后作为缓冲,否则程序运行失败
176 | while True:
177 | try:
178 | with open(monkey_log, 'rb') as monkeylog:
179 | time.sleep(2) # 每2秒采集一次
180 | apm.pid_mem(dev, Config.package_name, 1)
181 | apm.pid_cpuRate(dev, Config.package_name, 1)
182 | apm.pid_fps(dev, Config.package_name, 1)
183 | if monkeylog.read().count('Monkey finished') > 0:
184 | app[dev] = {"header": get_phone(dev)}
185 | app[dev]["header"]["net"] = Config.net
186 | pick.writeInfo(app, PATH(Config.info_path + "info.pickle"))
187 | print "--------------设备:%s 场景2:中等压力下测试完成----------------" % dev
188 | break
189 | except:
190 | break
191 |
192 | def fullMemTest(dev):
193 | print("--------------开始执行测试----------------")
194 | print("--------------设备:%s 场景3:满压力下APP性能指标----------------") % dev
195 | ad.adbStopActivity(dev, Config.package_name)
196 | run_time = time.strftime("%Y-%m-%d_%H%M%S", time.localtime(time.time()))
197 | monkeyStart(dev, run_time, 2)
198 | logProcess(dev, run_time)
199 | while True:
200 | try:
201 | with open(monkey_log, 'rb') as monkeylog:
202 | time.sleep(2) # 每2秒采集一次
203 | apm.pid_mem(dev, Config.package_name, 2)
204 | apm.pid_cpuRate(dev, Config.package_name, 2)
205 | #fps测试需要事先开启手机开发者模式里的GPU显示,否则运行出错
206 | apm.pid_fps(dev, Config.package_name, 2)
207 | if monkeylog.read().count('Monkey finished') > 0:
208 | print "--------------设备:%s 场景3:满压力下测试完成----------------" % dev
209 | break
210 | except:
211 | break
212 |
213 | def start(dev):
214 | rt = os.popen('adb devices').readlines() # os.popen()执行系统命令并返回执行后的结果
215 | num = len(rt) - 2
216 | app = {}
217 | Create_pickle(dev, num)
218 | unlockScreen(dev)
219 | # 中等压力下测试
220 | mediMemTest(dev, app)
221 | print '生成测试报告......'
222 | rep = Report(dev, "Alink V2.6.17 性能测试报告", "Medium")
223 | rep.createReport(dev)
224 | print '测试报告生成完毕'
225 |
226 | #启动MONKEY多线程
227 | class MonkeyTestThread(threading.Thread):
228 | def __init__(self, dev):
229 | threading.Thread.__init__(self)
230 | self.dev = dev
231 | self.thread_stop = False
232 |
233 | def run(self):
234 | time.sleep(2)
235 | start(self.dev)
236 |
237 |
238 |
239 | def create_threads_monkey(device_list):
240 | Thread_instances = []
241 | if device_list != []:
242 | for id_instance in device_list:
243 | dev = id_instance
244 | MontestInstance = MonkeyTestThread(dev)
245 | Thread_instances.append(MontestInstance)
246 | for instance in Thread_instances:
247 | instance.start()
248 |
249 |
250 |
251 | if __name__ == '__main__':
252 | device_dir = os.path.exists(AppPerCon.info_path)
253 | if device_dir:
254 | print ("持久性目录info已存在,继续执行测试!")
255 | else:
256 | #os.mkdir(AppPerformanceConfig.info_path) # 创建持久性目录,需要在文件存在的情况下创建二级目录
257 | os.makedirs(AppPerCon.info_path) # 使用makedirs可以在文件夹不存在的情况下直接创建
258 | device_list = apm.get_device()
259 | if ad.checkDevices():
260 | print("设备存在")
261 | create_threads_monkey(device_list)
262 | else:
263 | print("设备不存在")
264 |
265 |
266 |
--------------------------------------------------------------------------------
/testCase/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: UTF-8 -*-
--------------------------------------------------------------------------------