├── .idea ├── .name ├── encodings.xml ├── inspectionProfiles │ └── Project_Default.xml ├── misc.xml ├── modules.xml ├── monkey_test.iml ├── scopes │ └── scope_settings.xml ├── vcs.xml └── workspace.xml ├── Base ├── AdbCommon.py ├── BaseAnalysis.py ├── BaseCashEmnu.py ├── BaseFile.py ├── BaseMonitor.py ├── BaseMonkeyConfig.py ├── BasePhoneMsg.py ├── BasePickle.py ├── BaseReport.py ├── BaseWriteReport.py ├── Cprint.py ├── OperateFile.py ├── __init__.py └── __pycache__ │ ├── AdbCommon.cpython-34.pyc │ ├── BaseAnalysis.cpython-34.pyc │ ├── BaseCashEmnu.cpython-34.pyc │ ├── BaseFile.cpython-34.pyc │ ├── BaseMonitor.cpython-34.pyc │ ├── BaseMonkeyConfig.cpython-34.pyc │ ├── BasePhoneMsg.cpython-34.pyc │ ├── BasePickle.cpython-34.pyc │ ├── BaseReport.cpython-34.pyc │ ├── BaseWriteReport.cpython-34.pyc │ ├── Cprint.cpython-34.pyc │ ├── OperateFile.cpython-34.pyc │ └── __init__.cpython-34.pyc ├── Chinese.md ├── MainActivity.java ├── README.md ├── img ├── analysis.jpg ├── crash.PNG └── monitor.png ├── info ├── DU2TAN15AJ049163_battery.pickle ├── DU2TAN15AJ049163_cpu.pickle ├── DU2TAN15AJ049163_flow.pickle ├── DU2TAN15AJ049163_fps.pickle ├── DU2TAN15AJ049163_men.pickle ├── info.pickle └── sumInfo.pickle ├── kill5037.bat ├── log ├── adece0c8-1f61-4cae-8ed4-e8db510de83dlogcat.log ├── adece0c8-1f61-4cae-8ed4-e8db510de83dmonkey.log └── adece0c8-1f61-4cae-8ed4-e8db510de83dtraces.log ├── monkey.ini ├── monkey1.apk ├── monkeyTest.py └── report.xlsx /.idea/.name: -------------------------------------------------------------------------------- 1 | monkey_test -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 13 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/monkey_test.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/scopes/scope_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 14 | 15 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 129 | 130 | 131 | 132 | sum 133 | k 134 | ---- 135 | fps 136 | _maxFlow 137 | 93 138 | 117 139 | result 140 | -----flow--------- 141 | flow 142 | cpu 143 | maxCpu 144 | men 145 | mkdirInit 146 | 读取文件错误 147 | 148 | 149 | data 150 | 151 | 152 | 153 | 208 | 209 | 210 | true 211 | 212 | 213 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | Python 227 | 228 | 229 | 230 | 231 | PyArgumentListInspection 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 259 | 260 | 263 | 264 | 265 | 266 | 269 | 270 | 273 | 274 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 317 | 318 | 319 | 320 | 338 | 339 | 355 | 356 | 372 | 373 | 389 | 390 | 406 | 407 | 423 | 424 | 435 | 436 | 454 | 455 | 473 | 474 | 494 | 495 | 516 | 517 | 540 | 541 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 1442816524593 587 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 624 | 627 | 628 | 629 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 | 764 | 765 | 766 | 767 | 768 | 769 | 770 | 771 | 772 | 773 | 774 | 775 | 776 | 777 | 778 | 779 | 780 | 781 | 782 | 783 | 784 | 785 | 786 | 787 | 788 | 789 | 790 | 791 | 792 | 793 | 794 | 795 | 796 | 797 | 798 | 799 | 800 | 801 | 802 | 803 | 804 | 805 | 806 | 807 | 808 | 809 | 810 | 811 | 812 | 813 | 814 | -------------------------------------------------------------------------------- /Base/AdbCommon.py: -------------------------------------------------------------------------------- 1 | # python module for interacting with adb 2 | import os 3 | 4 | ''' 5 | 基本的adb操作 6 | ''' 7 | class AndroidDebugBridge(object): 8 | def call_adb(self, command): 9 | command_result = '' 10 | command_text = 'adb %s' % command 11 | print(command_text) 12 | results = os.popen(command_text, "r") 13 | while 1: 14 | line = results.readline() 15 | if not line: break 16 | command_result += line 17 | results.close() 18 | return command_result 19 | 20 | # check for any fastboot device 21 | def fastboot(self, device_id): 22 | pass 23 | 24 | # 检查设备 25 | def attached_devices(self): 26 | result = self.call_adb("devices") 27 | devices = result.partition('\n')[2].replace('\n', '').split('\tdevice') 28 | return [device for device in devices if len(device) > 2] 29 | # 状态 30 | def get_state(self): 31 | result = self.call_adb("get-state") 32 | result = result.strip(' \t\n\r') 33 | return result or None 34 | #重启 35 | def reboot(self, option): 36 | command = "reboot" 37 | if len(option) > 7 and option in ("bootloader", "recovery",): 38 | command = "%s %s" % (command, option.strip()) 39 | self.call_adb(command) 40 | 41 | # 将电脑文件拷贝到手机里面 42 | def push(self, local, remote): 43 | result = self.call_adb("push %s %s" % (local, remote)) 44 | return result 45 | 46 | # 拉数据到本地 47 | def pull(self, remote, local): 48 | result = self.call_adb("pull %s %s" % (remote, local)) 49 | return result 50 | # 同步更新 很少用此命名 51 | def sync(self, directory, **kwargs): 52 | command = "sync %s" % directory 53 | if 'list' in kwargs: 54 | command += " -l" 55 | result = self.call_adb(command) 56 | return result 57 | 58 | # 打开指定app 59 | def open_app(self,packagename,activity,devices): 60 | result = self.call_adb("-s "+ devices+" shell am start -n %s/%s" % (packagename, activity)) 61 | check = result.partition('\n')[2].replace('\n', '').split('\t ') 62 | if check[0].find("Error") >= 1: 63 | return False 64 | else: 65 | return True 66 | 67 | # 根据包名得到进程id 68 | def get_app_pid(self, pkg_name): 69 | string = self.call_adb("shell ps | grep "+pkg_name) 70 | # print(string) 71 | if string == '': 72 | return "the process doesn't exist." 73 | result = string.split(" ") 74 | # print(result[4]) 75 | return result[4] 76 | 77 | if __name__ == '__main__': 78 | 79 | reuslt = AndroidDebugBridge().attached_devices() 80 | for info in reuslt: 81 | 82 | print(info) 83 | -------------------------------------------------------------------------------- /Base/BaseAnalysis.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | 4 | # total 是rom容量 5 | def avgMen(men, total): 6 | if len(men): 7 | _men = [math.ceil(((men[i]) / total) * 1024) for i in range(len(men))] 8 | print(_men) 9 | return str(math.ceil(sum(_men) / len(_men))) + "M" 10 | return "0" 11 | 12 | 13 | def avgCpu(cpu): 14 | if len(cpu): 15 | resutl = "%.1f" % (sum(cpu) / len(cpu)) 16 | return str(math.ceil(float(resutl)*10)) + "%" 17 | return "0%" 18 | 19 | 20 | def avgFps(fps): 21 | if len(fps): 22 | return '%.2f' % float(str(math.ceil(sum(fps) / len(fps)))) 23 | return 0.00 24 | 25 | 26 | def maxMen(men): 27 | if len(men): 28 | print("men=" + str(men)) 29 | return str(math.ceil((max(men)) / 1024)) + "M" 30 | return "0M" 31 | 32 | 33 | def maxCpu(cpu): 34 | print("maxCpu="+str(cpu)) 35 | if len(cpu): 36 | result = "%.1f" % max(cpu) 37 | return str(math.ceil(float(result)*10)) + "%" 38 | return "0%" 39 | 40 | 41 | def maxFps(fps): 42 | return str(max(fps)) 43 | 44 | 45 | def maxFlow(flow): 46 | print("---maxFlow111----------") 47 | print(flow) 48 | _flowUp = [] 49 | _flowDown = [] 50 | for i in range(len(flow[0])): 51 | if i + 1 == len(flow[0]): 52 | break 53 | _flowUp.append(math.ceil((flow[0][i + 1] - flow[0][i]) / 1024)) 54 | print("---maxFlow2222---------") 55 | print(_flowUp) 56 | for i in range(len(flow[1])): 57 | if i + 1 == len(flow[1]): 58 | break 59 | _flowDown.append(math.ceil((flow[1][i + 1] - flow[1][i]) / 1024)) 60 | print("---maxFlow3333---------") 61 | print(_flowDown) 62 | if _flowUp: 63 | maxFpsUp = str(max(_flowUp)) + "KB" # 上行流量 64 | else: 65 | maxFpsUp = "0" 66 | if _flowDown: 67 | maxFpsDown = str(max(_flowDown)) + "KB" # 下行流量 68 | else: 69 | maxFpsDown = "0" 70 | return maxFpsUp, maxFpsDown 71 | 72 | def avgFlow(flow): 73 | _flowUp = [] 74 | _flowDown = [] 75 | for i in range(len(flow[0])): 76 | if i + 1 == len(flow[0]): 77 | break 78 | _flowUp.append((flow[0][i + 1] - flow[0][i])/1024) 79 | 80 | for i in range(len(flow[1])): 81 | if i + 1 == len(flow[1]): 82 | break 83 | _flowDown.append((flow[1][i + 1] - flow[1][i])/1024) 84 | avgFpsUp = str(math.ceil(sum(_flowUp) / len(_flowUp))) + "KB" 85 | avgFpsDown = str(math.ceil(sum(_flowDown) / len(_flowDown))) + "KB" 86 | return avgFpsUp, avgFpsDown 87 | 88 | if __name__ == '__main__': 89 | flow = [[93919172, 94987124, 96309507], [14250800, 14285269, 14331153]] 90 | cpu = [1.9164759725400458, 0.40045766590389015, 0.8493771234428086, 1.8407534246575343] 91 | men = [310171, 323267, 321179, 317913, 316569, 335277, 323853, 315837, 333765, 333829, 337433, 337473, 339877, 328953, 328881, 328909, 334029, 329873, 334645, 338649, 332541, 329273, 333581] 92 | 93 | print(avgMen(men, 3014000)) 94 | # print(maxFlow(flow)) 95 | -------------------------------------------------------------------------------- /Base/BaseCashEmnu.py: -------------------------------------------------------------------------------- 1 | __author__ = 'Administrator' 2 | 3 | ANR = "ANR" 4 | I_ANR = 0 5 | CRASH = "CRASH" 6 | I_CRASH = 0 7 | EXCEPTION = "Exception" 8 | I_EXCEPTION = 0 9 | 10 | # finish实际已经测试完设备个数 11 | # devices 测试设备个数 12 | info = [] 13 | finish = 0 14 | -------------------------------------------------------------------------------- /Base/BaseFile.py: -------------------------------------------------------------------------------- 1 | __author__ = 'shikun' 2 | import os 3 | 4 | ''' 5 | 操作文件 6 | ''' 7 | class OperateFile: 8 | #method(r,w,a) 9 | def __init__(self, file, method='w+'): 10 | self.file = file 11 | self.method = method 12 | self.fileHandle = None 13 | 14 | def write_txt(self, line): 15 | OperateFile(self.file).check_file() 16 | self.fileHandle = open(self.file, self.method) 17 | self.fileHandle.write(line + "\n") 18 | self.fileHandle.close() 19 | 20 | def read_txt_row(self): 21 | resutl = "" 22 | if OperateFile(self.file).check_file(): 23 | self.fileHandle = open(self.file, self.method) 24 | resutl = self.fileHandle.readline() 25 | self.fileHandle.close() 26 | return resutl 27 | 28 | def read_txt_rows(self): 29 | if OperateFile(self.file).check_file(): 30 | self.fileHandle = open(self.file, self.method) 31 | file_list = self.fileHandle.readlines() 32 | for i in file_list: 33 | print(i.strip("\n")) 34 | self.fileHandle.close() 35 | def check_file(self): 36 | if not os.path.isfile(self.file): 37 | # print('文件不存在' + self.file) 38 | # sys.exit() 39 | return False 40 | else: 41 | return True 42 | # print("文件存在!") 43 | 44 | def mkdir_file(self): 45 | if not os.path.isfile(self.file): 46 | f = open(self.file, self.method) 47 | f.close() 48 | print("创建文件成功") 49 | else: 50 | print("文件已经存在") 51 | def remove_file(self): 52 | if os.path.isfile(self.file): 53 | os.remove(self.file) 54 | print("删除文件成功") 55 | else: 56 | print("文件不存在") 57 | # if __name__ == '__main__': 58 | # bf = OperateFile("text.xml") 59 | # if bf.check_file() == False: 60 | # bf.mkdir_file() 61 | # bf.write_txt("111") -------------------------------------------------------------------------------- /Base/BaseMonitor.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import os 3 | import re 4 | from wsgiref.validate import validator 5 | import time 6 | from Base.BasePickle import * 7 | PATH = lambda p: os.path.abspath( 8 | os.path.join(os.path.dirname(__file__), p) 9 | ) 10 | 11 | 12 | 13 | 14 | def get_men(pkg_name, devices): 15 | try: 16 | cmd = "adb -s " + devices +" shell dumpsys meminfo %s" % (pkg_name) 17 | print(cmd) 18 | output = subprocess.check_output(cmd).split() 19 | # print(output) 20 | s_men = ".".join([x.decode() for x in output]) # 转换为string 21 | print(s_men) 22 | men2 = int(re.findall("TOTAL.(\d+)*", s_men, re.S)[0]) 23 | except: 24 | men2 = 0 25 | writeInfo(men2, PATH("../info/" + devices + "_men.pickle")) 26 | return men2 27 | # men_s = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.readlines() 28 | # for info in men_s: 29 | # if len(info.split()) and info.split()[0].decode() == "TOTAL": 30 | # # print("men="+info.split()[1].decode()) 31 | # men.append(int(info.split()[1].decode())) 32 | # # writeInfo(int(info.split()[1].decode()), PATH("../info/" + devices + "_men.pickle")) 33 | # print("----men----") 34 | # print(men) 35 | # return men 36 | 37 | 38 | # 得到fps 39 | ''' 40 | @author fenfenzhong 41 | ''' 42 | 43 | 44 | def get_fps(pkg_name, devices): 45 | _adb = "adb -s " + devices +" shell dumpsys gfxinfo %s" % pkg_name 46 | print(_adb) 47 | results = os.popen(_adb).read().strip() 48 | frames = [x for x in results.split('\n') if validator(x)] 49 | frame_count = len(frames) 50 | jank_count = 0 51 | vsync_overtime = 0 52 | render_time = 0 53 | for frame in frames: 54 | time_block = re.split(r'\s+', frame.strip()) 55 | if len(time_block) == 3: 56 | try: 57 | render_time = float(time_block[0]) + float(time_block[1]) + float(time_block[2]) 58 | except Exception as e: 59 | render_time = 0 60 | 61 | ''' 62 | 当渲染时间大于16.67,按照垂直同步机制,该帧就已经渲染超时 63 | 那么,如果它正好是16.67的整数倍,比如66.68,则它花费了4个垂直同步脉冲,减去本身需要一个,则超时3个 64 | 如果它不是16.67的整数倍,比如67,那么它花费的垂直同步脉冲应向上取整,即5个,减去本身需要一个,即超时4个,可直接算向下取整 65 | 66 | 最后的计算方法思路: 67 | 执行一次命令,总共收集到了m帧(理想情况下m=128),但是这m帧里面有些帧渲染超过了16.67毫秒,算一次jank,一旦jank, 68 | 需要用掉额外的垂直同步脉冲。其他的就算没有超过16.67,也按一个脉冲时间来算(理想情况下,一个脉冲就可以渲染完一帧) 69 | 70 | 所以FPS的算法可以变为: 71 | m / (m + 额外的垂直同步脉冲) * 60 72 | ''' 73 | if render_time > 16.67: 74 | jank_count += 1 75 | if render_time % 16.67 == 0: 76 | vsync_overtime += int(render_time / 16.67) - 1 77 | else: 78 | vsync_overtime += int(render_time / 16.67) 79 | 80 | _fps = int(frame_count * 60 / (frame_count + vsync_overtime)) 81 | writeInfo(_fps, PATH("../info/" + devices + "_fps.pickle")) 82 | 83 | # return (frame_count, jank_count, fps) 84 | print("-----fps------") 85 | print(_fps) 86 | 87 | 88 | def get_battery(devices): 89 | try: 90 | cmd = "adb -s " + devices + " shell dumpsys battery" 91 | print(cmd) 92 | output = subprocess.check_output(cmd).split() 93 | # _batter = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, 94 | # stderr=subprocess.PIPE).stdout.readlines() 95 | st = ".".join([x.decode() for x in output]) # 转换为string 96 | print(st) 97 | battery2 = int(re.findall("level:.(\d+)*", st, re.S)[0]) 98 | 99 | except: 100 | battery2 = 90 101 | writeInfo(battery2, PATH("../info/" + devices + "_battery.pickle")) 102 | 103 | return battery2 104 | 105 | 106 | 107 | def get_pid(pkg_name, devices): 108 | cmd = "adb -s " + devices + " shell ps | findstr " + pkg_name 109 | print("----get_pid-------") 110 | print(cmd) 111 | pid = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, 112 | stderr=subprocess.PIPE).stdout.readlines() 113 | for item in pid: 114 | if item.split()[8].decode() == pkg_name: 115 | return item.split()[1].decode() 116 | 117 | 118 | def get_flow(pid, type, devices): 119 | # pid = get_pid(pkg_name) 120 | upflow = downflow = 0 121 | if pid is not None: 122 | cmd = "adb -s " + devices + " shell cat /proc/" + pid + "/net/dev" 123 | print(cmd) 124 | _flow = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, 125 | stderr=subprocess.PIPE).stdout.readlines() 126 | for item in _flow: 127 | if type == "wifi" and item.split()[0].decode() == "wlan0:": # wifi 128 | # 0 上传流量,1 下载流量 129 | upflow = int(item.split()[1].decode()) 130 | downflow = int(item.split()[9].decode()) 131 | print("------flow---------") 132 | print(upflow) 133 | break 134 | if type == "gprs" and item.split()[0].decode() == "rmnet0:": # gprs 135 | print("-----flow---------") 136 | upflow = int(item.split()[1].decode()) 137 | downflow = int(item.split()[9].decode()) 138 | print(upflow) 139 | break 140 | 141 | writeFlowInfo(upflow, downflow, PATH("../info/" + devices + "_flow.pickle")) 142 | 143 | ''' 144 | 每一个cpu快照均 145 | ''' 146 | def totalCpuTime(devices): 147 | user=nice=system=idle=iowait=irq=softirq= 0 148 | ''' 149 | user:从系统启动开始累计到当前时刻,处于用户态的运行时间,不包含 nice值为负进程。 150 | nice:从系统启动开始累计到当前时刻,nice值为负的进程所占用的CPU时间 151 | system 从系统启动开始累计到当前时刻,处于核心态的运行时间 152 | idle 从系统启动开始累计到当前时刻,除IO等待时间以外的其它等待时间 153 | iowait 从系统启动开始累计到当前时刻,IO等待时间(since 2.5.41) 154 | irq 从系统启动开始累计到当前时刻,硬中断时间(since 2.6.0-test4) 155 | softirq 从系统启动开始累计到当前时刻,软中断时间(since 2.6.0-test4) 156 | stealstolen 这是时间花在其他的操作系统在虚拟环境中运行时(since 2.6.11) 157 | guest 这是运行时间guest 用户Linux内核的操作系统的控制下的一个虚拟CPU(since 2.6.24) 158 | ''' 159 | 160 | cmd = "adb -s " + devices +" shell cat /proc/stat" 161 | print(cmd) 162 | p = subprocess.Popen(cmd, stdout=subprocess.PIPE, 163 | stderr=subprocess.PIPE, 164 | stdin=subprocess.PIPE, shell=True) 165 | (output, err) = p.communicate() 166 | res = output.split() 167 | 168 | for info in res: 169 | if info.decode() == "cpu": 170 | user = res[1].decode() 171 | nice = res[2].decode() 172 | system = res[3].decode() 173 | idle = res[4].decode() 174 | iowait = res[5].decode() 175 | irq = res[6].decode() 176 | softirq = res[7].decode() 177 | print("user=" + user) 178 | print("nice=" + nice) 179 | print("system=" + system) 180 | print("idle=" + idle) 181 | print("iowait=" + iowait) 182 | print("irq=" + irq) 183 | print("softirq=" + softirq) 184 | result = int(user) + int(nice) + int(system) + int(idle) + int(iowait) + int(irq) + int(softirq) 185 | print("totalCpuTime"+str(result)) 186 | return result 187 | 188 | 189 | 190 | ''' 191 | 每一个进程快照 192 | ''' 193 | def processCpuTime(pid, devices): 194 | ''' 195 | 196 | pid 进程号 197 | utime 该任务在用户态运行的时间,单位为jiffies 198 | stime 该任务在核心态运行的时间,单位为jiffies 199 | cutime 所有已死线程在用户态运行的时间,单位为jiffies 200 | cstime 所有已死在核心态运行的时间,单位为jiffies 201 | ''' 202 | utime=stime=cutime=cstime = 0 203 | try: 204 | cmd = "adb -s "+ devices + " shell cat /proc/" + pid +"/stat" 205 | print(cmd) 206 | p = subprocess.Popen(cmd, stdout=subprocess.PIPE, 207 | stderr=subprocess.PIPE, 208 | stdin=subprocess.PIPE, shell=True) 209 | (output, err) = p.communicate() 210 | res = output.split() 211 | 212 | utime = res[13].decode() 213 | stime = res[14].decode() 214 | cutime = res[15].decode() 215 | cstime = res[16].decode() 216 | print("utime="+utime) 217 | print("stime="+stime) 218 | print("cutime="+cutime) 219 | print("cstime="+cstime) 220 | result = int(utime) + int(stime) + int(cutime) + int(cstime) 221 | print("processCpuTime="+str(result)) 222 | except : 223 | result = 0 224 | return result 225 | 226 | # 得到几核cpu 227 | def get_cpu_kel(devices): 228 | cmd = "adb -s " + devices + " shell cat /proc/cpuinfo" 229 | print(cmd) 230 | output = subprocess.check_output(cmd).split() 231 | sitem = ".".join([x.decode() for x in output]) # 转换为string 232 | return len(re.findall("processor", sitem)) 233 | 234 | ''' 235 | 计算某进程的cpu使用率 236 | 100*( processCpuTime2 – processCpuTime1) / (totalCpuTime2 – totalCpuTime1) (按100%计算,如果是多核情况下还需乘以cpu的个数); 237 | cpukel cpu几核 238 | pid 进程id 239 | ''' 240 | def cpu_rate(pid, cpukel, devices): 241 | # pid = get_pid(pkg_name) 242 | processCpuTime1 = processCpuTime(pid, devices) 243 | time.sleep(1) 244 | processCpuTime2 = processCpuTime(pid, devices) 245 | processCpuTime3 = processCpuTime2 - processCpuTime1 246 | 247 | totalCpuTime1 = totalCpuTime(devices) 248 | time.sleep(1) 249 | totalCpuTime2 = totalCpuTime(devices) 250 | totalCpuTime3 = (totalCpuTime2 - totalCpuTime1)*cpukel 251 | print("totalCpuTime3="+str(totalCpuTime3)) 252 | print("processCpuTime3="+str(processCpuTime3)) 253 | 254 | cpu = 100 * (processCpuTime3) / (totalCpuTime3) 255 | writeInfo(cpu, PATH("../info/" + devices + "_cpu.pickle")) 256 | print("--------cpu--------") 257 | print(cpu) 258 | if __name__ == '__main__': 259 | 260 | # cpu_rate("2749") 261 | pid = get_pid("com.jianshu.haruki", "DU2TAN15AJ049163") 262 | # print(pid) 263 | # get_flow(pid, "wifi", "DU2TAN15AJ049163") 264 | # get_battery("DU2TAN15AJ049163") 265 | # get_men("com.jianshu.haruki", "DU2TAN15AJ049163") 266 | # print(get_cpu_kel()) 267 | # cpu_kel = get_cpu_kel("DU2TAN15AJ049163") 268 | # print(cpu_rate(pid,cpu_kel,"DU2TAN15AJ049163")) 269 | get_flow(pid, "gprs", "emulator-5554") 270 | # print(get_flow("com.jianshu.haruki", "gprs")) 271 | # print(get_flow("com.jianshu.haruki", "gprs")) 272 | # print(get_flow("com.jianshu.haruki", "gprs")) 273 | -------------------------------------------------------------------------------- /Base/BaseMonkeyConfig.py: -------------------------------------------------------------------------------- 1 | __author__ = 'Administrator' 2 | import configparser 3 | import time 4 | import os 5 | PATH = lambda p: os.path.abspath( 6 | os.path.join(os.path.dirname(__file__), p) 7 | ) 8 | 9 | def monkeyConfig(init_file): 10 | config = configparser.ConfigParser() 11 | config.read(init_file) 12 | app = {} 13 | app["package_name"] = config['DEFAULT']['package_name'] 14 | # app["activity"] = config['DEFAULT']['activity'] 15 | app["net"] = config['DEFAULT']['net'] 16 | app["cmd"] = config['DEFAULT']['cmd'] + ">" 17 | return app 18 | -------------------------------------------------------------------------------- /Base/BasePhoneMsg.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import time 4 | 5 | __author__ = 'shikun' 6 | import re 7 | import subprocess 8 | 9 | 10 | def stop_monkey(dev): 11 | monkey_name = "com.android.commands.monkey" 12 | print("--------------------") 13 | pid = subprocess.Popen("adb -s " + dev + " shell ps | findstr " + monkey_name, shell=True, stdout=subprocess.PIPE,stderr=subprocess.PIPE).stdout.readlines() 14 | if pid =="": 15 | print("No monkey running in %s" % dev) 16 | else: 17 | for item in pid: 18 | if item.split()[8].decode() == monkey_name: 19 | monkey_pid = item.split()[1].decode() 20 | cmd_monkey = "adb -s " + dev + " shell kill %s" % (monkey_pid) 21 | os.popen(cmd_monkey) 22 | print("Monkey in %s was killed" % dev) 23 | time.sleep(2) 24 | subprocess.Popen("taskkill /f /t /im python.exe", shell=True) 25 | 26 | def reboot(dev): 27 | cmd_reboot = "adb -s " + dev + " reboot" 28 | os.popen(cmd_reboot) 29 | 30 | def getModel( devices): 31 | result = {} 32 | cmd = "adb -s " + devices + " shell cat /system/build.prop" 33 | print(cmd) 34 | # output = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.readlines() 35 | output = subprocess.check_output(cmd).decode() 36 | result["release"] = re.findall("version.release=(\d\.\d)*", output, re.S)[0] # Android 系统,如anroid 4.0 37 | result["phone_name"] = re.findall("ro.product.model=(\S+)*", output, re.S)[0] # 手机名 38 | result["phone_model"] = re.findall("ro.product.brand=(\S+)*", output, re.S)[0] # 手机品牌 39 | return result 40 | 41 | 42 | def get_men_total(devices): 43 | cmd = "adb -s " + devices + " shell cat /proc/meminfo" 44 | print(cmd) 45 | output = subprocess.check_output(cmd).split() 46 | # item = [x.decode() for x in output] 47 | return int(output[1].decode()) 48 | 49 | # # 得到几核cpu 50 | def get_cpu_kel(devices): 51 | cmd = "adb -s " + devices +" shell cat /proc/cpuinfo" 52 | print(cmd) 53 | output = subprocess.check_output(cmd).split() 54 | sitem = ".".join([x.decode() for x in output]) # 转换为string 55 | return str(len(re.findall("processor", sitem))) + "核" 56 | 57 | 58 | # 得到手机分辨率 59 | def get_app_pix(devices): 60 | cmd = "adb -s " + devices + " shell wm size" 61 | print(cmd) 62 | return subprocess.check_output(cmd).split()[2].decode() 63 | 64 | # 65 | def get_phone_Kernel(devices): 66 | pix = get_app_pix(devices) 67 | men_total = get_men_total(devices) 68 | phone_msg = getModel(devices) 69 | cpu_sum = get_cpu_kel(devices) 70 | return phone_msg, men_total, cpu_sum, pix 71 | if __name__ == '__main__': 72 | # get_app_pix("emulator-5554") 73 | stop_monkey("DU2TAN15AJ049163") -------------------------------------------------------------------------------- /Base/BasePickle.py: -------------------------------------------------------------------------------- 1 | __author__ = "shikun" 2 | import pickle 3 | import os 4 | 5 | PATH = lambda p: os.path.abspath( 6 | os.path.join(os.path.dirname(__file__), p) 7 | ) 8 | 9 | 10 | def writeSum(init, data=None, path="data.pickle"): 11 | if init == 0: 12 | result = data 13 | else: 14 | _read = readInfo(path) 15 | result = _read - 1 16 | 17 | with open(path, 'wb') as f: 18 | print("------writeSum-------") 19 | print(result) 20 | pickle.dump(result, f) 21 | 22 | 23 | def readSum(path): 24 | data = {} 25 | with open(path, 'rb') as f: 26 | try: 27 | data = pickle.load(f) 28 | except EOFError: 29 | data = {} 30 | print("读取文件错误") 31 | print("------read-------") 32 | print(path) 33 | print(data) 34 | return data 35 | 36 | 37 | def readInfo(path): 38 | data = [] 39 | with open(path, 'rb') as f: 40 | try: 41 | data = pickle.load(f) 42 | # print(data) 43 | except EOFError: 44 | data = [] 45 | # print("读取文件错误") 46 | print("------read-------") 47 | print(path) 48 | print(data) 49 | return data 50 | 51 | 52 | def writeInfo(data, path="data.pickle"): 53 | _read = readInfo(path) 54 | result = [] 55 | if _read: 56 | _read.append(data) 57 | result = _read 58 | else: 59 | result.append(data) 60 | with open(path, 'wb') as f: 61 | print("------writeInfo-------") 62 | print(result) 63 | pickle.dump(result, f) 64 | 65 | def writeFlowInfo(upflow, downflow, path="data.pickle"): 66 | print("---data-----") 67 | print("上行流量="+str(upflow)) 68 | print("下行流量="+str(downflow)) 69 | 70 | _read = readInfo(path) 71 | result = [[], []] 72 | if _read: 73 | _read[0].append(upflow) 74 | _read[1].append(downflow) 75 | result = _read 76 | else: 77 | result[0].append(upflow) 78 | result[1].append(downflow) 79 | with open(path, 'wb') as f: 80 | print("------writeFlowInfo-------") 81 | print(result) 82 | pickle.dump(result, f) 83 | 84 | 85 | if __name__ == "__main__": 86 | # readInfo(PATH("../info/DU2TAN15AJ049163_battery.pickle")) 87 | # readInfo(PATH("../info/emulator-5554_fps.pickle")) 88 | # readInfo(PATH("../info/emulator-5554_battery.pickle")) 89 | # readInfo(PATH("../info/emulator-5554_men.pickle")) 90 | # readInfo(PATH("../info/DU2TAN15AJ049163_men.pickle")) 91 | # readInfo(PATH("../info/emulator-5554_flow.pickle")) 92 | readInfo("E:\\app\\py\\monkey1\\info\\info.pickle") 93 | # readInfo(PATH("../info/DU2TAN15AJ049163_cpu.pickle")) 94 | -------------------------------------------------------------------------------- /Base/BaseReport.py: -------------------------------------------------------------------------------- 1 | import math 2 | import re 3 | 4 | import xlsxwriter 5 | 6 | from Base import BaseAnalysis, BaseCashEmnu as go 7 | from Base.BasePickle import readInfo 8 | 9 | 10 | class OperateReport: 11 | def __init__(self, wd): 12 | self.wd = wd 13 | self._crashM = [] 14 | # self.pie(self.wd, worksheet) 15 | 16 | def monitor(self, info): 17 | worksheet = self.wd.add_worksheet("Analysis") 18 | worksheet.set_column("A:A", 15) 19 | worksheet.set_column("B:B", 10) 20 | worksheet.set_column("C:C", 10) 21 | worksheet.set_column("D:D", 10) 22 | worksheet.set_column("E:E", 10) 23 | worksheet.set_column("F:F", 10) 24 | worksheet.set_column("G:G", 10) 25 | worksheet.set_column("H:H", 10) 26 | worksheet.set_column("I:I", 10) 27 | worksheet.set_column("J:J", 10) 28 | worksheet.set_column("K:K", 10) 29 | worksheet.set_column("L:L", 10) 30 | worksheet.set_column("L:L", 10) 31 | worksheet.set_column("M:M", 10) 32 | worksheet.set_column("N:N", 10) 33 | worksheet.set_column("O:O", 10) 34 | worksheet.set_column("P:P", 10) 35 | worksheet.set_column("Q:Q", 10) 36 | worksheet.set_column("R:R", 10) 37 | 38 | worksheet.set_row(1, 30) 39 | worksheet.set_row(2, 30) 40 | worksheet.set_row(3, 30) 41 | worksheet.set_row(4, 30) 42 | worksheet.set_row(5, 30) 43 | worksheet.set_row(6, 30) 44 | worksheet.set_row(7, 30) 45 | worksheet.set_row(8, 30) 46 | worksheet.set_row(9, 30) 47 | worksheet.set_row(10, 30) 48 | worksheet.set_row(11, 30) 49 | worksheet.set_row(12, 30) 50 | 51 | define_format_H1 = get_format(self.wd, {'bold': True, 'font_size': 18}) 52 | define_format_H2 = get_format(self.wd, {'bold': True, 'font_size': 14}) 53 | define_format_H1.set_border(1) 54 | 55 | define_format_H2.set_border(1) 56 | define_format_H1.set_align("center") 57 | define_format_H2.set_align("center") 58 | define_format_H2.set_bg_color("blue") 59 | define_format_H2.set_color("#ffffff") 60 | worksheet.merge_range('A1:L1', 'monkey性能监控', define_format_H1) 61 | _write_center(worksheet, "A2", '设备名', self.wd) 62 | _write_center(worksheet, "B2", 'CPU', self.wd) 63 | _write_center(worksheet, "C2", '内存', self.wd) 64 | _write_center(worksheet, "D2", '分辨率', self.wd) 65 | _write_center(worksheet, "E2", '网络', self.wd) 66 | _write_center(worksheet, "F2", "耗时", self.wd) 67 | _write_center(worksheet, "G2", "CPU峰值", self.wd) 68 | _write_center(worksheet, "H2", "CPU均值", self.wd) 69 | _write_center(worksheet, "I2", "内存峰值", self.wd) 70 | _write_center(worksheet, "J2", "内存均值", self.wd) 71 | _write_center(worksheet, "K2", "fps峰值", self.wd) 72 | _write_center(worksheet, "L2", "fps均值", self.wd) 73 | _write_center(worksheet, "M2", "电量测试之前", self.wd) 74 | _write_center(worksheet, "N2", "电量测试之后", self.wd) 75 | _write_center(worksheet, "O2", "上行流量峰值", self.wd) 76 | _write_center(worksheet, "P2", "上行流量均值", self.wd) 77 | _write_center(worksheet, "Q2", "下行流量峰值", self.wd) 78 | _write_center(worksheet, "R2", "下行流量均值", self.wd) 79 | 80 | 81 | temp = 3 82 | for t in info: 83 | for wrap in t: 84 | for item in t[wrap]: 85 | self.getCrashMsg(t[wrap]["header"]["monkey_log"]) 86 | _write_center(worksheet, "A" + str(temp), t[wrap]["header"]["phone_name"], self.wd) 87 | _write_center(worksheet, "B" + str(temp), t[wrap]["header"]["kel"], self.wd) 88 | _write_center(worksheet, "C" + str(temp), str(math.ceil(t[wrap]["header"]["rom"] / 1024)) + "M", self.wd) 89 | _write_center(worksheet, "D" + str(temp), t[wrap]["header"]["pix"], self.wd) 90 | _write_center(worksheet, "E" + str(temp), t[wrap]["header"]["net"], self.wd) 91 | _write_center(worksheet, "F" + str(temp), t[wrap]["header"]["time"], self.wd) 92 | 93 | cpu = readInfo(t[wrap]["cpu"]) 94 | men = readInfo(t[wrap]["men"]) 95 | fps = readInfo(t[wrap]["fps"]) 96 | flow = readInfo(t[wrap]["flow"]) 97 | print("----wrap-----") 98 | print(flow) 99 | _write_center(worksheet, "G" + str(temp), BaseAnalysis.maxCpu(cpu), self.wd) 100 | _write_center(worksheet, "H" + str(temp), BaseAnalysis.avgCpu(cpu), self.wd) 101 | _write_center(worksheet, "I" + str(temp), BaseAnalysis.maxMen(men), self.wd) 102 | _write_center(worksheet, "J" + str(temp), BaseAnalysis.avgMen(men, t[wrap]["header"]["rom"]), self.wd) 103 | _write_center(worksheet, "K" + str(temp), BaseAnalysis.maxFps(fps), self.wd) 104 | _write_center(worksheet, "L" + str(temp), BaseAnalysis.avgFps(fps), self.wd) 105 | _write_center(worksheet, "M" + str(temp), t[wrap]["header"]["beforeBattery"], self.wd) 106 | _write_center(worksheet, "N" + str(temp), t[wrap]["header"]["afterBattery"], self.wd) 107 | 108 | _maxFlow = BaseAnalysis.maxFlow(flow) 109 | _avgFLow = BaseAnalysis.avgFlow(flow) 110 | print("-----_maxFlow----------") 111 | print(_maxFlow) 112 | _write_center(worksheet, "O" + str(temp), _maxFlow[0], self.wd) 113 | _write_center(worksheet, "Q" + str(temp), _maxFlow[1], self.wd) 114 | _write_center(worksheet, "P" + str(temp), _avgFLow[1], self.wd) 115 | _write_center(worksheet, "R" + str(temp), _avgFLow[1], self.wd) 116 | 117 | break 118 | temp = temp + 1 119 | 120 | def getCrashMsg(self, log): 121 | with open(log, encoding="utf-8") as monkey_log: 122 | lines = monkey_log.readlines() 123 | for line in lines: 124 | if re.findall(go.ANR, line): 125 | print("存在anr错误:" + line) 126 | self._crashM.append(line) 127 | if re.findall(go.CRASH, line): 128 | print("存在crash错误:" + line) 129 | self._crashM.append(line) 130 | if re.findall(go.EXCEPTION, line): 131 | print("存在crash错误:" + line) 132 | self._crashM.append(line) 133 | def crash(self): 134 | if len(self._crashM): 135 | worksheet = self.wd.add_worksheet("crash") 136 | _write_center(worksheet, "A1", '崩溃统计日志', self.wd) 137 | temp = 2 138 | for item in self._crashM: 139 | _write_center(worksheet, "A" + str(temp), item, self.wd) 140 | temp = temp + 1 141 | 142 | def plot(self, worksheet, types, lenData, name): 143 | ''' 144 | 145 | :param worksheet: 146 | :param types: cpu,fps,flow,battery 147 | :param lenData: 数据长度 148 | :param name: sheet名字 149 | :return: 150 | ''' 151 | values = "" 152 | row = "" 153 | title = "" 154 | if types == "cpu": 155 | values = "="+name+"!$A$1:$A$" + str(lenData + 1) 156 | row = 'A' + str(lenData) 157 | title = "cpu使用率" 158 | elif types == "men": 159 | values = "="+name+"!$B$1:$B$" + str(lenData + 1) 160 | row = 'B' + str(lenData) 161 | title = "内存使用MB" 162 | elif types == "fps": 163 | values = "=" + name + "!$C$1:$C$" + str(lenData + 1) 164 | row = 'C' + str(lenData) 165 | title = "fps使用情况" 166 | elif types == "battery": 167 | values = "="+name+"!$D$1:$D$" + str(lenData + 1) 168 | row = 'D' + str(lenData) 169 | title = "电池剩余%" 170 | elif types == "flowUp": 171 | values = "="+name+"!$E$1:$E$" + str(lenData + 1) 172 | row = 'E' + str(lenData) 173 | title = "上行流量KB" 174 | elif types == "flowDown": 175 | values = "="+name+"!$F$1:$F$" + str(lenData + 1) 176 | row = 'F' + str(lenData) 177 | title = "下行流量KB" 178 | chart1 = self.wd.add_chart({'type': 'line'}) 179 | chart1.add_series({ 180 | 'values': values 181 | }) 182 | chart1.set_title({'name': title}) 183 | # worksheet.insert_chart('A9', chart1, {'x_offset': 2, 'y_offset': 2}) 184 | worksheet.insert_chart(row, chart1) 185 | 186 | 187 | 188 | def close(self): 189 | self.wd.close() 190 | 191 | def analysis(self, info): 192 | for t in info: 193 | for wrap in t: 194 | name = wrap + "detail" # sheet名字 195 | worksheet = self.wd.add_worksheet(name) 196 | worksheet.set_column("A:A", 10) 197 | worksheet.set_column("B:B", 10) 198 | worksheet.set_column("C:C", 10) 199 | worksheet.set_column("D:D", 10) 200 | worksheet.set_column("E:E", 10) 201 | worksheet.set_column("F:F", 10) 202 | 203 | worksheet.set_row(1, 30) 204 | worksheet.set_row(2, 30) 205 | worksheet.set_row(3, 30) 206 | worksheet.set_row(4, 30) 207 | worksheet.set_row(5, 30) 208 | worksheet.set_row(6, 30) 209 | define_format_H1 = get_format(self.wd, {'bold': True, 'font_size': 18}) 210 | define_format_H2 = get_format(self.wd, {'bold': True, 'font_size': 14}) 211 | define_format_H1.set_border(1) 212 | 213 | define_format_H2.set_border(1) 214 | define_format_H1.set_align("center") 215 | define_format_H2.set_align("center") 216 | define_format_H2.set_bg_color("blue") 217 | define_format_H2.set_color("#ffffff") 218 | 219 | _write_center(worksheet, "A1", 'cpu(%)', self.wd) 220 | _write_center(worksheet, "B1", 'men(M)', self.wd) 221 | _write_center(worksheet, "C1", 'fps', self.wd) 222 | _write_center(worksheet, "D1", 'battery(%)', self.wd) 223 | _write_center(worksheet, "E1", '上行流量(KB)', self.wd) 224 | _write_center(worksheet, "F1", '下行流量(KB)', self.wd) 225 | for item in t[wrap]: 226 | print("------data-----") 227 | temp = 2 228 | cpu = readInfo(t[wrap]["cpu"]) 229 | for item in cpu: 230 | _write_center(worksheet, "A" + str(temp), float("%.1f" % item)*10, self.wd) 231 | temp = temp + 1 232 | 233 | temp = 2 234 | men = readInfo(t[wrap]["men"]) 235 | for item in men: 236 | _write_center(worksheet, "B" + str(temp), math.ceil(item/1024), self.wd) 237 | temp = temp + 1 238 | 239 | 240 | temp = 2 241 | fps = readInfo(t[wrap]["fps"]) 242 | for item in fps: 243 | _write_center(worksheet, "C" + str(temp), item, self.wd) 244 | temp = temp + 1 245 | 246 | temp = 2 247 | battery = readInfo(t[wrap]["battery"]) 248 | for item in battery: 249 | _write_center(worksheet, "D" + str(temp), item, self.wd) 250 | temp = temp + 1 251 | 252 | temp = 2 253 | flow = readInfo(t[wrap]["flow"]) 254 | for item in flow[0]: 255 | if item > 0: 256 | _write_center(worksheet, "E" + str(temp), math.ceil(item/1024), self.wd) 257 | else: 258 | _write_center(worksheet, "E" + str(temp), 0, self.wd) 259 | temp = temp + 1 260 | 261 | temp = 2 262 | for item in flow[1]: 263 | if item > 0: 264 | _write_center(worksheet, "F" + str(temp), math.ceil(item/1024), self.wd) 265 | else: 266 | _write_center(worksheet, "F" + str(temp), 0, self.wd) 267 | temp = temp + 1 268 | self.plot(worksheet, "cpu", len(cpu), name) 269 | self.plot(worksheet, "men", len(men), name) 270 | self.plot(worksheet, "battery", len(battery), name) 271 | self.plot(worksheet, "fps", len(fps), name) 272 | self.plot(worksheet, "flowUp", len(flow[0]), name) 273 | self.plot(worksheet, "flowDown", len(flow[1]), name) 274 | break 275 | 276 | 277 | def get_format(wd, option={}): 278 | return wd.add_format(option) 279 | 280 | 281 | def get_format_center(wd, num=1): 282 | return wd.add_format({'align': 'center', 'valign': 'vcenter', 'border': num}) 283 | 284 | 285 | def set_border_(wd, num=1): 286 | return wd.add_format({}).set_border(num) 287 | 288 | 289 | def _write_center(worksheet, cl, data, wd): 290 | return worksheet.write(cl, data, get_format_center(wd)) 291 | 292 | 293 | def set_row(worksheet, num, height): 294 | worksheet.set_row(num, height) 295 | 296 | 297 | if __name__ == '__main__': 298 | 299 | workbook = xlsxwriter.Workbook('report.xlsx') 300 | info = [{'emulator-5554': {'cpu': 'E:\\app\\py\\monkey1\\info\\emulator-5554_cpu.pickle', 'battery': 'E:\\app\\py\\monkey1\\info\\emulator-5554_battery.pickle', 'men': 'E:\\app\\py\\monkey1\\info\\emulator-5554_men.pickle', 'flow': 'E:\\app\\py\\monkey1\\info\\emulator-5554_flow.pickle', 'header': {'rom': 770300, 'kel': '2核', 'monkey_log': 'E:\\app\\py\\monkey1\\log\\55dd9a83-3337-46d5-bb1f-6f64b85be7cbmonkey.log', 'beforeBattery': 99, 'pix': '1440x810', 'time': '10秒', 'afterBattery': 99, 'phone_name': 'GT-I9500_samsung_4.4', 'net': 'gprs'}, 'fps': 'E:\\app\\py\\monkey1\\info\\emulator-5554_fps.pickle'}}, {'DU2TAN15AJ049163': {'cpu': 'E:\\app\\py\\monkey1\\info\\DU2TAN15AJ049163_cpu.pickle', 'battery': 'E:\\app\\py\\monkey1\\info\\DU2TAN15AJ049163_battery.pickle', 'men': 'E:\\app\\py\\monkey1\\info\\DU2TAN15AJ049163_men.pickle', 'flow': 'E:\\app\\py\\monkey1\\info\\DU2TAN15AJ049163_flow.pickle', 'header': {'rom': 3085452, 'kel': '8核', 'monkey_log': 'E:\\app\\py\\monkey1\\log\\732ac6cd-dd84-4818-80ea-d9b5339c6774monkey.log', 'beforeBattery': 94, 'pix': '1080x1920', 'time': '15秒', 'afterBattery': 94, 'phone_name': 'H60-L02_Huawei_4.4', 'net': 'gprs'}, 'fps': 'E:\\app\\py\\monkey1\\info\\DU2TAN15AJ049163_fps.pickle'}}] 301 | 302 | 303 | tem = OperateReport(workbook) 304 | tem.monitor(info) 305 | tem.analysis(info) 306 | tem.crash() 307 | tem.close() 308 | # print(len(data["cpu"])) 309 | -------------------------------------------------------------------------------- /Base/BaseWriteReport.py: -------------------------------------------------------------------------------- 1 | import os 2 | import xlsxwriter 3 | from Base import BaseReport 4 | 5 | 6 | PATH = lambda p: os.path.abspath( 7 | os.path.join(os.path.dirname(__file__), p) 8 | ) 9 | 10 | 11 | def report(info): 12 | workbook = xlsxwriter.Workbook('report.xlsx') 13 | bo = BaseReport.OperateReport(workbook) 14 | bo.monitor(info) 15 | bo.crash() 16 | bo.analysis(info) 17 | bo.close() -------------------------------------------------------------------------------- /Base/Cprint.py: -------------------------------------------------------------------------------- 1 | __author__ = 'Administrator' 2 | import ctypes 3 | 4 | STD_INPUT_HANDLE = -10 5 | STD_OUTPUT_HANDLE= -11 6 | STD_ERROR_HANDLE = -12 7 | 8 | FOREGROUND_BLACK = 0x0 9 | FOREGROUND_BLUE = 0x01 # text color contains blue. 10 | FOREGROUND_GREEN= 0x02 # text color contains green. 11 | FOREGROUND_RED = 0x04 # text color contains red. 12 | FOREGROUND_INTENSITY = 0x08 # text color is intensified. 13 | 14 | BACKGROUND_BLUE = 0x10 # background color contains blue. 15 | BACKGROUND_GREEN= 0x20 # background color contains green. 16 | BACKGROUND_RED = 0x40 # background color contains red. 17 | BACKGROUND_INTENSITY = 0x80 # background color is intensified. 18 | 19 | class Color: 20 | ''''' See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winprog/winprog/windows_api_reference.asp 21 | for information on Windows APIs.''' 22 | std_out_handle = ctypes.windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE) 23 | 24 | def set_cmd_color(self, color, handle=std_out_handle): 25 | """(color) -> bit 26 | Example: set_cmd_color(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY) 27 | """ 28 | bool = ctypes.windll.kernel32.SetConsoleTextAttribute(handle, color) 29 | return bool 30 | 31 | def reset_color(self): 32 | self.set_cmd_color(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE) 33 | 34 | def print_red_text(self, print_text): 35 | self.set_cmd_color(FOREGROUND_RED | FOREGROUND_INTENSITY) 36 | print(print_text) 37 | self.reset_color() 38 | 39 | def print_green_text(self, print_text): 40 | self.set_cmd_color(FOREGROUND_GREEN | FOREGROUND_INTENSITY) 41 | print(print_text) 42 | self.reset_color() 43 | 44 | def print_blue_text(self, print_text): 45 | self.set_cmd_color(FOREGROUND_BLUE | FOREGROUND_INTENSITY) 46 | print(print_text) 47 | self.reset_color() 48 | 49 | def print_red_text_with_blue_bg(self, print_text): 50 | self.set_cmd_color(FOREGROUND_RED | FOREGROUND_INTENSITY| BACKGROUND_BLUE | BACKGROUND_INTENSITY) 51 | print(print_text) 52 | self.reset_color() -------------------------------------------------------------------------------- /Base/OperateFile.py: -------------------------------------------------------------------------------- 1 | __author__ = 'Administrator' 2 | import os 3 | class base_file: 4 | #method(r,w,a) 5 | def __init__(self, file, method='w+'): 6 | self.file = file 7 | self.method = method 8 | self.fileHandle = None 9 | 10 | def write_txt(self, line): 11 | base_file(self.file).check_file() 12 | self.fileHandle = open(self.file, self.method) 13 | self.fileHandle.write(line + "\n") 14 | self.fileHandle.close() 15 | 16 | def read_txt_row(self): 17 | base_file(self.file).check_file() 18 | self.fileHandle = open(self.file, self.method) 19 | print(self.fileHandle.readline()) 20 | self.fileHandle.close() 21 | 22 | def read_txt_rows(self): 23 | base_file(self.file).check_file() 24 | self.fileHandle = open(self.file, self.method) 25 | file_list = self.fileHandle.readlines() 26 | for i in file_list: 27 | print(i.strip("\n")) 28 | self.fileHandle.close() 29 | def check_file(self): 30 | if not os.path.isfile(self.file): 31 | # print('文件不存在' + self.file) 32 | # sys.exit() 33 | return False 34 | else: 35 | return True 36 | # print("文件存在!") 37 | 38 | def mkdir_file(self): 39 | if not os.path.isfile(self.file): 40 | f = open(self.file, self.method) 41 | f.close() 42 | print("创建文件成功") 43 | return True 44 | else: 45 | print("文件已经存在") 46 | return False 47 | def remove_file(self): 48 | if os.path.isfile(self.file): 49 | os.remove(self.file) 50 | print("删除文件成功") 51 | else: 52 | print("文件不存在") 53 | # if __name__ == '__main__': 54 | # bf = base_file("text.xml") 55 | # if bf.check_file() == False: 56 | # bf.mkdir_file() 57 | # bf.write_txt("111") -------------------------------------------------------------------------------- /Base/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Louis-me/monkeyTest/1dc89a5f5765e1dcc2fd5bfb8e457ad37e014de6/Base/__init__.py -------------------------------------------------------------------------------- /Base/__pycache__/AdbCommon.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Louis-me/monkeyTest/1dc89a5f5765e1dcc2fd5bfb8e457ad37e014de6/Base/__pycache__/AdbCommon.cpython-34.pyc -------------------------------------------------------------------------------- /Base/__pycache__/BaseAnalysis.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Louis-me/monkeyTest/1dc89a5f5765e1dcc2fd5bfb8e457ad37e014de6/Base/__pycache__/BaseAnalysis.cpython-34.pyc -------------------------------------------------------------------------------- /Base/__pycache__/BaseCashEmnu.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Louis-me/monkeyTest/1dc89a5f5765e1dcc2fd5bfb8e457ad37e014de6/Base/__pycache__/BaseCashEmnu.cpython-34.pyc -------------------------------------------------------------------------------- /Base/__pycache__/BaseFile.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Louis-me/monkeyTest/1dc89a5f5765e1dcc2fd5bfb8e457ad37e014de6/Base/__pycache__/BaseFile.cpython-34.pyc -------------------------------------------------------------------------------- /Base/__pycache__/BaseMonitor.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Louis-me/monkeyTest/1dc89a5f5765e1dcc2fd5bfb8e457ad37e014de6/Base/__pycache__/BaseMonitor.cpython-34.pyc -------------------------------------------------------------------------------- /Base/__pycache__/BaseMonkeyConfig.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Louis-me/monkeyTest/1dc89a5f5765e1dcc2fd5bfb8e457ad37e014de6/Base/__pycache__/BaseMonkeyConfig.cpython-34.pyc -------------------------------------------------------------------------------- /Base/__pycache__/BasePhoneMsg.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Louis-me/monkeyTest/1dc89a5f5765e1dcc2fd5bfb8e457ad37e014de6/Base/__pycache__/BasePhoneMsg.cpython-34.pyc -------------------------------------------------------------------------------- /Base/__pycache__/BasePickle.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Louis-me/monkeyTest/1dc89a5f5765e1dcc2fd5bfb8e457ad37e014de6/Base/__pycache__/BasePickle.cpython-34.pyc -------------------------------------------------------------------------------- /Base/__pycache__/BaseReport.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Louis-me/monkeyTest/1dc89a5f5765e1dcc2fd5bfb8e457ad37e014de6/Base/__pycache__/BaseReport.cpython-34.pyc -------------------------------------------------------------------------------- /Base/__pycache__/BaseWriteReport.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Louis-me/monkeyTest/1dc89a5f5765e1dcc2fd5bfb8e457ad37e014de6/Base/__pycache__/BaseWriteReport.cpython-34.pyc -------------------------------------------------------------------------------- /Base/__pycache__/Cprint.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Louis-me/monkeyTest/1dc89a5f5765e1dcc2fd5bfb8e457ad37e014de6/Base/__pycache__/Cprint.cpython-34.pyc -------------------------------------------------------------------------------- /Base/__pycache__/OperateFile.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Louis-me/monkeyTest/1dc89a5f5765e1dcc2fd5bfb8e457ad37e014de6/Base/__pycache__/OperateFile.cpython-34.pyc -------------------------------------------------------------------------------- /Base/__pycache__/__init__.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Louis-me/monkeyTest/1dc89a5f5765e1dcc2fd5bfb8e457ad37e014de6/Base/__pycache__/__init__.cpython-34.pyc -------------------------------------------------------------------------------- /Chinese.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Louis-me/monkeyTest/1dc89a5f5765e1dcc2fd5bfb8e457ad37e014de6/Chinese.md -------------------------------------------------------------------------------- /MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.monkneytest; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.util.Log; 6 | import android.view.View; 7 | import android.view.View.OnClickListener; 8 | import android.widget.Button; 9 | public class MainActivity extends Activity { 10 | Button btn; 11 | @Override 12 | protected void onCreate(Bundle savedInstanceState) { 13 | super.onCreate(savedInstanceState); 14 | 15 | setContentView(R.layout.activity_main); 16 | btn = (Button) findViewById(R.id.btn1); 17 | btn.setOnClickListener(newOnClickListener); 18 | 19 | } 20 | private OnClickListener newOnClickListener = new OnClickListener(){ 21 | @Override 22 | public void onClick(View v) { 23 | String a =null; a.toString(); 24 | } 25 | }; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Louis-me/monkeyTest/1dc89a5f5765e1dcc2fd5bfb8e457ad37e014de6/README.md -------------------------------------------------------------------------------- /img/analysis.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Louis-me/monkeyTest/1dc89a5f5765e1dcc2fd5bfb8e457ad37e014de6/img/analysis.jpg -------------------------------------------------------------------------------- /img/crash.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Louis-me/monkeyTest/1dc89a5f5765e1dcc2fd5bfb8e457ad37e014de6/img/crash.PNG -------------------------------------------------------------------------------- /img/monitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Louis-me/monkeyTest/1dc89a5f5765e1dcc2fd5bfb8e457ad37e014de6/img/monitor.png -------------------------------------------------------------------------------- /info/DU2TAN15AJ049163_battery.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Louis-me/monkeyTest/1dc89a5f5765e1dcc2fd5bfb8e457ad37e014de6/info/DU2TAN15AJ049163_battery.pickle -------------------------------------------------------------------------------- /info/DU2TAN15AJ049163_cpu.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Louis-me/monkeyTest/1dc89a5f5765e1dcc2fd5bfb8e457ad37e014de6/info/DU2TAN15AJ049163_cpu.pickle -------------------------------------------------------------------------------- /info/DU2TAN15AJ049163_flow.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Louis-me/monkeyTest/1dc89a5f5765e1dcc2fd5bfb8e457ad37e014de6/info/DU2TAN15AJ049163_flow.pickle -------------------------------------------------------------------------------- /info/DU2TAN15AJ049163_fps.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Louis-me/monkeyTest/1dc89a5f5765e1dcc2fd5bfb8e457ad37e014de6/info/DU2TAN15AJ049163_fps.pickle -------------------------------------------------------------------------------- /info/DU2TAN15AJ049163_men.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Louis-me/monkeyTest/1dc89a5f5765e1dcc2fd5bfb8e457ad37e014de6/info/DU2TAN15AJ049163_men.pickle -------------------------------------------------------------------------------- /info/info.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Louis-me/monkeyTest/1dc89a5f5765e1dcc2fd5bfb8e457ad37e014de6/info/info.pickle -------------------------------------------------------------------------------- /info/sumInfo.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Louis-me/monkeyTest/1dc89a5f5765e1dcc2fd5bfb8e457ad37e014de6/info/sumInfo.pickle -------------------------------------------------------------------------------- /kill5037.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | color a 3 | title ReleaseAdbPort 4 | echo ====================== 5 | echo *** liyu 2015-01-15*** 6 | echo *** v1.0.0 *** 7 | echo ====================== 8 | echo --------------------------- 9 | echo Checking adb port... 10 | for /F "usebackq tokens=5" %%a in (`"netstat -ano | findstr "5037""`) do ( 11 | if not "%%a" =="0" call :ReleasePort %%a 12 | ) 13 | echo --------------------------- 14 | echo adb port has been released! 15 | echo --------------------------- 16 | 17 | 18 | exit 19 | 20 | :ReleasePort 21 | TASKKILL /f /PID %1 22 | 23 | exit -------------------------------------------------------------------------------- /log/adece0c8-1f61-4cae-8ed4-e8db510de83dmonkey.log: -------------------------------------------------------------------------------- 1 | :Monkey: seed=1518933798525 count=500 2 | :AllowPackage: com.jianshu.haruki 3 | :IncludeCategory: android.intent.category.LAUNCHER 4 | :IncludeCategory: android.intent.category.MONKEY 5 | // Selecting main activities from category android.intent.category.LAUNCHER 6 | // - NOT USING main activity com.android.browser.BrowserActivity (from package com.android.browser) 7 | // - NOT USING main activity com.android.contacts.activities.PeopleActivity (from package com.android.contacts) 8 | // - NOT USING main activity com.android.contacts.activities.DialtactsActivity (from package com.android.contacts) 9 | // - NOT USING main activity com.android.mms.ui.ConversationList (from package com.android.contacts) 10 | // - NOT USING main activity com.huawei.gallery.app.GalleryActivity (from package com.android.gallery3d) 11 | // - NOT USING main activity com.android.email.activity.Welcome (from package com.android.email) 12 | // - NOT USING main activity com.huawei.camera (from package com.huawei.camera) 13 | // - NOT USING main activity com.android.settings.HWSettings (from package com.android.settings) 14 | // - NOT USING main activity com.android.calculator2.Calculator (from package com.android.calculator2) 15 | // - NOT USING main activity com.android.calendar.AllInOneActivity (from package com.android.calendar) 16 | // - NOT USING main activity com.android.deskclock.AlarmsMainActivity (from package com.android.deskclock) 17 | // - NOT USING main activity com.huawei.android.hicloud.hisync.activity.NewHiSyncSettingActivity (from package com.huawei.android.ds) 18 | // - NOT USING main activity com.android.mediacenter.PageActivity (from package com.android.mediacenter) 19 | // - NOT USING main activity com.example.android.notepad.NotePadActivity (from package com.example.android.notepad) 20 | // - NOT USING main activity com.huawei.hidisk.filemanager.FileManager (from package com.huawei.hidisk) 21 | // - NOT USING main activity com.google.android.apps.chrome.Main (from package com.android.chrome) 22 | // - NOT USING main activity com.evernote.ui.HomeActivity (from package com.evernote) 23 | // - NOT USING main activity com.tencent.pangu.link.SplashActivity (from package com.tencent.android.qqdownloader) 24 | // - NOT USING main activity com.sohu.inputmethod.sogou.SogouIMELauncher (from package com.sohu.inputmethod.sogou) 25 | // - NOT USING main activity com.baidu.baidumaps.WelcomeScreen (from package com.baidu.BaiduMap) 26 | // - NOT USING main activity com.huawei.phoneservice.ui.HelpCenterActivity (from package com.huawei.phoneservice) 27 | // - NOT USING main activity com.huawei.hwvplayer.framework.MainActivity (from package com.huawei.hwvplayer) 28 | // - NOT USING main activity com.android.keyguard.keyguardplus.OneKeyLockActivity (from package com.android.keyguard) 29 | // - NOT USING main activity com.android.providers.downloads.ui.DownloadList (from package com.android.providers.downloads.ui) 30 | // - NOT USING main activity com.huawei.KoBackup.InitializeActivity (from package com.huawei.KoBackup) 31 | // - NOT USING main activity com.huawei.android.FMRadio.FMRadioMainActivity (from package com.huawei.android.FMRadio) 32 | // - NOT USING main activity com.huawei.vassistant.ui.VAssistantActivity (from package com.huawei.vassistant) 33 | // - NOT USING main activity com.huawei.android.hwouc.ui.activities.MainEntranceActivity (from package com.huawei.android.hwouc) 34 | // - NOT USING main activity com.android.soundrecorder.SoundRecorder (from package com.android.soundrecorder) 35 | // - NOT USING main activity com.huawei.systemmanager.mainscreen.MainScreenActivity (from package com.huawei.systemmanager) 36 | // - NOT USING main activity com.huawei.android.thememanager.HwThemeManagerActivity (from package com.huawei.android.thememanager) 37 | // - NOT USING main activity com.huawei.vdrive.ui.VDriveActivity (from package com.huawei.vdrive) 38 | // - NOT USING main activity com.huawei.android.totemweather.WeatherHome (from package com.huawei.android.totemweather) 39 | // - NOT USING main activity com.huawei.magnifier.MagnifierActivity (from package com.huawei.magnifier) 40 | // - NOT USING main activity com.android.stk.StkLauncherActivity (from package com.android.stk) 41 | // - NOT USING main activity com.android.stk.StkLauncherActivity2 (from package com.android.stk) 42 | // - NOT USING main activity com.android.systemui.flashlight.FlashlightActivity (from package com.android.systemui) 43 | // - NOT USING main activity com.android.hwmirror.Mirror (from package com.android.hwmirror) 44 | // - NOT USING main activity com.huawei.android.remotecontroller.StartActivity (from package com.huawei.android.remotecontroller) 45 | // - NOT USING main activity com.huawei.appmarket.MainActivity (from package com.huawei.appmarket) 46 | // - NOT USING main activity com.autonavi.map.activity.SplashActivity (from package com.autonavi.minimap) 47 | // - NOT USING main activity com.kingroot.kinguser.activitys.SliderMainActivity-Entry (from package com.kingroot.kinguser) 48 | // - NOT USING main activity com.example.monkey.MainActivity (from package com.example.monkey) 49 | // - NOT USING main activity com.alipay.mobile.quinox.LauncherActivity (from package com.MobileTicket) 50 | // - NOT USING main activity io.appium.settings.Settings (from package io.appium.settings) 51 | // + Using main activity com.baiji.jianshu.ui.splash.SplashScreenActivity (from package com.jianshu.haruki) 52 | // - NOT USING main activity com.jecelyin.editor.JecEditor (from package com.jecelyin.editor) 53 | // - NOT USING main activity io.appium.unlock.Unlock (from package io.appium.unlock) 54 | // - NOT USING main activity com.jingdong.app.mall.main.MainActivity (from package com.jingdong.app.mall) 55 | // - NOT USING main activity com.tencent.mtt.SplashActivity (from package com.tencent.mtt) 56 | // - NOT USING main activity com.intsig.camscanner.WelcomeActivity (from package com.intsig.camscanner) 57 | // - NOT USING main activity com.tencent.qqmail.LaucherActivity (from package com.tencent.androidqqmail) 58 | // - NOT USING main activity cn.etouch.ecalendar.ECalendar (from package cn.etouch.ecalendar) 59 | // - NOT USING main activity com.sankuai.meituan.activity.Welcome (from package com.sankuai.meituan) 60 | // - NOT USING main activity com.baidu.netdisk.ui.Navigate (from package com.baidu.netdisk) 61 | // - NOT USING main activity com.speedsoftware.rootexplorer.RootExplorer (from package com.speedsoftware.rootexplorer) 62 | // - NOT USING main activity com.oasisfeng.greenify.GreenifyActivity (from package com.oasisfeng.greenify) 63 | // - NOT USING main activity com.netease.cloudmusic.activity.LoadingActivity (from package com.netease.cloudmusic) 64 | // - NOT USING main activity com.tencent.qqlive.ona.activity.WelcomeActivity (from package com.tencent.qqlive) 65 | // - NOT USING main activity com.sinovatech.unicom.ui.WelcomeClient (from package com.sinovatech.unicom.ui) 66 | // - NOT USING main activity com.xxAssistant.View.SplashActivity (from package com.xxAssistant) 67 | // - NOT USING main activity com.tencent.tmgp.supercell.clashofclans.GameAppTencent (from package com.tencent.tmgp.supercell.clashofclans) 68 | // - NOT USING main activity com.tencent.mm.ui.LauncherUI (from package com.tencent.mm) 69 | // - NOT USING main activity so.ofo.labofo.activities.EntryActivity (from package so.ofo.labofo) 70 | // - NOT USING main activity com.yipiao.activity.LaunchActivity (from package com.yipiao) 71 | // - NOT USING main activity com.mobike.mobikeapp.SplashActivity (from package com.mobike.mobikeapp) 72 | // - NOT USING main activity com.eg.android.AlipayGphone.AlipayLogin (from package com.eg.android.AlipayGphone) 73 | // - NOT USING main activity com.didi.sdk.app.DidiLoadDexActivity (from package com.sdu.didi.psnger) 74 | // - NOT USING main activity dev.xesam.chelaile.app.module.func.SplashActivity (from package com.ygkj.chelaile.standard) 75 | // - NOT USING main activity com.tencent.mobileqq.activity.SplashActivity (from package com.tencent.mobileqq) 76 | // - NOT USING main activity com.zhihu.android.app.ui.activity.MainActivity (from package com.zhihu.android) 77 | // - NOT USING main activity com.tencent.news.activity.SplashActivity (from package com.tencent.news) 78 | // - NOT USING main activity com.tencent.tmgp.sgame.SGameActivity (from package com.tencent.tmgp.sgame) 79 | // Selecting main activities from category android.intent.category.MONKEY 80 | // - NOT USING main activity com.android.settings.Settings$RunningServicesActivity (from package com.android.settings) 81 | // - NOT USING main activity com.android.settings.Settings$StorageUseActivity (from package com.android.settings) 82 | // - NOT USING main activity com.huawei.android.launcher.Launcher (from package com.huawei.android.launcher) 83 | // Seeded: 1518933798525 84 | // Event percentages: 85 | // 0: 15.0% 86 | // 1: 10.0% 87 | // 2: 2.0% 88 | // 3: 15.0% 89 | // 4: -0.0% 90 | // 5: 25.0% 91 | // 6: 15.0% 92 | // 7: 2.0% 93 | // 8: 2.0% 94 | // 9: 1.0% 95 | // 10: 13.0% 96 | :Switch: #Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.jianshu.haruki/com.baiji.jianshu.ui.splash.SplashScreenActivity;end 97 | // Allowing start of Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.jianshu.haruki/com.baiji.jianshu.ui.splash.SplashScreenActivity } in package com.jianshu.haruki 98 | Sleeping for 500 milliseconds 99 | :Sending Key (ACTION_DOWN): 20 // KEYCODE_DPAD_DOWN 100 | :Sending Key (ACTION_UP): 20 // KEYCODE_DPAD_DOWN 101 | Sleeping for 500 milliseconds 102 | // Allowing start of Intent { cmp=com.jianshu.haruki/com.baiji.jianshu.MainActivity } in package com.jianshu.haruki 103 | // activityResuming(com.jianshu.haruki) 104 | // activityResuming(com.jianshu.haruki) 105 | :Sending Key (ACTION_DOWN): 164 // KEYCODE_VOLUME_MUTE 106 | :Sending Key (ACTION_UP): 164 // KEYCODE_VOLUME_MUTE 107 | Sleeping for 500 milliseconds 108 | :Sending Key (ACTION_DOWN): 126 // KEYCODE_MEDIA_PLAY 109 | :Sending Key (ACTION_UP): 126 // KEYCODE_MEDIA_PLAY 110 | Sleeping for 500 milliseconds 111 | :Switch: #Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.jianshu.haruki/com.baiji.jianshu.ui.splash.SplashScreenActivity;end 112 | // Allowing start of Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.jianshu.haruki/com.baiji.jianshu.ui.splash.SplashScreenActivity } in package com.jianshu.haruki 113 | Sleeping for 500 milliseconds 114 | :Sending Key (ACTION_DOWN): 21 // KEYCODE_DPAD_LEFT 115 | :Sending Key (ACTION_UP): 21 // KEYCODE_DPAD_LEFT 116 | Sleeping for 500 milliseconds 117 | :Sending Key (ACTION_DOWN): 253 // 253 118 | :Sending Key (ACTION_UP): 253 // 253 119 | Sleeping for 500 milliseconds 120 | :Sending Key (ACTION_DOWN): 20 // KEYCODE_DPAD_DOWN 121 | :Sending Key (ACTION_UP): 20 // KEYCODE_DPAD_DOWN 122 | Sleeping for 500 milliseconds 123 | :Sending Key (ACTION_DOWN): 22 // KEYCODE_DPAD_RIGHT 124 | :Sending Key (ACTION_UP): 22 // KEYCODE_DPAD_RIGHT 125 | Sleeping for 500 milliseconds 126 | :Sending Key (ACTION_DOWN): 23 // KEYCODE_DPAD_CENTER 127 | :Sending Key (ACTION_UP): 23 // KEYCODE_DPAD_CENTER 128 | Sleeping for 500 milliseconds 129 | :Sending Key (ACTION_DOWN): 20 // KEYCODE_DPAD_DOWN 130 | :Sending Key (ACTION_UP): 20 // KEYCODE_DPAD_DOWN 131 | Sleeping for 500 milliseconds 132 | :Sending Touch (ACTION_DOWN): 0:(10.0,51.0) 133 | :Sending Touch (ACTION_POINTER_DOWN 1): 0:(9.24655,50.689335) 1:(741.0,810.0) 134 | :Sending Touch (ACTION_MOVE): 0:(7.588022,49.52343) 1:(747.7333,808.75116) 135 | :Sending Touch (ACTION_MOVE): 0:(4.4343414,48.509113) 1:(758.92554,797.54) 136 | :Sending Touch (ACTION_MOVE): 0:(0.0,48.21961) 1:(771.9343,785.41644) 137 | :Sending Touch (ACTION_MOVE): 0:(0.0,47.021748) 1:(793.7777,778.644) 138 | :Sending Touch (ACTION_MOVE): 0:(0.0,46.606693) 1:(796.2478,769.4633) 139 | :Sending Touch (ACTION_POINTER_UP 1): 0:(0.0,45.48305) 1:(818.06445,760.0704) 140 | :Sending Touch (ACTION_UP): 0:(0.0,44.87091) 141 | Sleeping for 500 milliseconds 142 | :Sending Key (ACTION_DOWN): 20 // KEYCODE_DPAD_DOWN 143 | :Sending Key (ACTION_UP): 20 // KEYCODE_DPAD_DOWN 144 | Sleeping for 500 milliseconds 145 | :Sending Key (ACTION_DOWN): 19 // KEYCODE_DPAD_UP 146 | :Sending Key (ACTION_UP): 19 // KEYCODE_DPAD_UP 147 | Sleeping for 500 milliseconds 148 | :Sending Key (ACTION_DOWN): 23 // KEYCODE_DPAD_CENTER 149 | :Sending Key (ACTION_UP): 23 // KEYCODE_DPAD_CENTER 150 | Sleeping for 500 milliseconds 151 | :Sending Trackball (ACTION_MOVE): 0:(1.0,-3.0) 152 | :Sending Trackball (ACTION_MOVE): 0:(-4.0,0.0) 153 | :Sending Trackball (ACTION_MOVE): 0:(-1.0,-3.0) 154 | :Sending Trackball (ACTION_MOVE): 0:(3.0,1.0) 155 | :Sending Trackball (ACTION_MOVE): 0:(4.0,-5.0) 156 | :Sending Trackball (ACTION_MOVE): 0:(-2.0,0.0) 157 | :Sending Trackball (ACTION_MOVE): 0:(-4.0,-3.0) 158 | :Sending Trackball (ACTION_MOVE): 0:(1.0,2.0) 159 | :Sending Trackball (ACTION_MOVE): 0:(-1.0,-1.0) 160 | :Sending Trackball (ACTION_MOVE): 0:(1.0,1.0) 161 | :Sending Key (ACTION_DOWN): 82 // KEYCODE_MENU 162 | :Sending Key (ACTION_UP): 82 // KEYCODE_MENU 163 | Sleeping for 500 milliseconds 164 | :Sending Touch (ACTION_DOWN): 0:(637.0,1292.0) 165 | :Sending Touch (ACTION_UP): 0:(629.91626,1311.5186) 166 | Sleeping for 500 milliseconds 167 | :Sending Touch (ACTION_DOWN): 0:(670.0,765.0) 168 | :Sending Touch (ACTION_UP): 0:(677.3006,767.5015) 169 | Sleeping for 500 milliseconds 170 | :Sending Touch (ACTION_DOWN): 0:(375.0,367.0) 171 | :Sending Touch (ACTION_UP): 0:(374.69092,378.29987) 172 | Sleeping for 500 milliseconds 173 | :Sending Touch (ACTION_DOWN): 0:(475.0,1195.0) 174 | :Sending Touch (ACTION_UP): 0:(482.29504,1175.4089) 175 | Sleeping for 500 milliseconds 176 | :Sending Key (ACTION_DOWN): 22 // KEYCODE_DPAD_RIGHT 177 | :Sending Key (ACTION_UP): 22 // KEYCODE_DPAD_RIGHT 178 | Sleeping for 500 milliseconds 179 | :Sending Key (ACTION_DOWN): 21 // KEYCODE_DPAD_LEFT 180 | :Sending Key (ACTION_UP): 21 // KEYCODE_DPAD_LEFT 181 | Sleeping for 500 milliseconds 182 | :Sending Key (ACTION_DOWN): 302 // 302 183 | :Sending Key (ACTION_UP): 302 // 302 184 | -------------------------------------------------------------------------------- /monkey.ini: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | cmd=monkey -p com.jianshu.haruki --throttle 500 --ignore-timeouts --ignore-crashes --monitor-native-crashes -v -v -v 500 > 3 | package_name=com.jianshu.haruki 4 | activity = com.baiji.jianshu.account.SplashScreenActivity 5 | net = gprs -------------------------------------------------------------------------------- /monkey1.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Louis-me/monkeyTest/1dc89a5f5765e1dcc2fd5bfb8e457ad37e014de6/monkey1.apk -------------------------------------------------------------------------------- /monkeyTest.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import pickle 3 | 4 | import subprocess 5 | import shutil 6 | import threading 7 | 8 | from multiprocessing import Process 9 | 10 | from Base.BasePickle import writeInfo, writeSum, readInfo 11 | from Base.BaseWriteReport import report 12 | __author__ = 'shikun' 13 | import datetime 14 | import uuid 15 | import time 16 | from multiprocessing import Pool 17 | 18 | from Base.BaseFile import OperateFile 19 | import os 20 | from Base import AdbCommon 21 | from Base import BaseMonkeyConfig 22 | 23 | from Base import BasePhoneMsg 24 | from Base import BaseMonitor 25 | 26 | PATH = lambda p: os.path.abspath( 27 | os.path.join(os.path.dirname(__file__), p) 28 | ) 29 | 30 | ba = AdbCommon.AndroidDebugBridge() 31 | 32 | 33 | info = [] 34 | 35 | 36 | # 手机信息 37 | def get_phome(devices): 38 | bg = BasePhoneMsg.get_phone_Kernel(devices) 39 | app = {} 40 | app["phone_name"] = bg[0]["phone_name"] + "_" + bg[0]["phone_model"] + "_" + bg[0]["release"] 41 | app["pix"] = bg[3] 42 | app["rom"] = bg[1] 43 | app["kel"] = bg[2] 44 | return app 45 | 46 | 47 | def mkdirInit(devices, app, data=None): 48 | # destroy(devices) 49 | cpu = PATH("./info/" + devices + "_cpu.pickle") 50 | men = PATH("./info/" + devices + "_men.pickle") 51 | flow = PATH("./info/" + devices + "_flow.pickle") 52 | battery = PATH("./info/" + devices + "_battery.pickle") 53 | fps = PATH("./info/" + devices + "_fps.pickle") 54 | app[devices] = {"cpu": cpu, "men": men, "flow": flow, "battery": battery, "fps": fps, "header": get_phome(devices)} 55 | OperateFile(cpu).mkdir_file() 56 | OperateFile(men).mkdir_file() 57 | OperateFile(flow).mkdir_file() 58 | OperateFile(battery).mkdir_file() 59 | OperateFile(fps).mkdir_file() 60 | OperateFile(PATH("./info/sumInfo.pickle")).mkdir_file() # 用于记录是否已经测试完毕,里面存的是一个整数 61 | OperateFile(PATH("./info/info.pickle")).mkdir_file() # 用于记录统计结果的信息,是[{}]的形式 62 | 63 | writeSum(0, data, PATH("./info/sumInfo.pickle")) # 初始化记录当前真实连接的设备数 64 | 65 | def runnerPool(): 66 | shutil.rmtree((PATH("./info/"))) # 删除持久化目录 67 | os.makedirs(PATH("./info/")) # 创建持久化目录 68 | devices_Pool = [] 69 | devices = ba.attached_devices() 70 | if devices: 71 | for item in range(0, len(devices)): 72 | _app = {} 73 | _app["devices"] = devices[item] 74 | _app["num"] = len(devices) 75 | devices_Pool.append(_app) 76 | pool = Pool(len(devices)) 77 | pool.map(start, devices_Pool) 78 | pool.close() 79 | pool.join() 80 | else: 81 | print("设备不存在") 82 | 83 | 84 | def start(devicess): 85 | devices = devicess["devices"] 86 | num = devicess["num"] 87 | app = {} 88 | mkdirInit(devices, app, num) 89 | mc = BaseMonkeyConfig.monkeyConfig(PATH("monkey.ini")) 90 | # 打开想要的activity 91 | # ba.open_app(mc["package_name"], mc["activity"], devices) 留着备用可以统计每次打开哪个页面的启动时间等 92 | # monkey开始测试 93 | mc["log"] = PATH("./log") + "\\" + str(uuid.uuid4()) 94 | mc["monkey_log"] = mc["log"] + "monkey.log" 95 | mc["cmd"] = mc['cmd'] + mc["monkey_log"] 96 | start_monkey("adb -s " + devices + " shell " + mc["cmd"], mc["log"]) 97 | time.sleep(1) 98 | starttime = datetime.datetime.now() 99 | pid = BaseMonitor.get_pid(mc["package_name"], devices) 100 | cpu_kel = BaseMonitor.get_cpu_kel(devices) 101 | beforeBattery = BaseMonitor.get_battery(devices) 102 | while True: 103 | with open(mc["monkey_log"], encoding='utf-8') as monkeylog: 104 | time.sleep(1) # 每1秒采集检查一次 105 | BaseMonitor.cpu_rate(pid, cpu_kel, devices) 106 | BaseMonitor.get_men(mc["package_name"], devices) 107 | BaseMonitor.get_fps(mc["package_name"], devices) 108 | BaseMonitor.get_flow(pid, mc["net"], devices) 109 | BaseMonitor.get_battery(devices) 110 | if monkeylog.read().count('Monkey finished') > 0: 111 | endtime = datetime.datetime.now() 112 | print(str(devices)+"测试完成咯") 113 | writeSum(1, path=PATH("./info/sumInfo.pickle")) 114 | app[devices] ["header"]["beforeBattery"] = beforeBattery 115 | app[devices]["header"]["afterBattery"] = BaseMonitor.get_battery(devices) 116 | app[devices]["header"]["net"] = mc["net"] 117 | app[devices]["header"]["monkey_log"] = mc["monkey_log"] 118 | app[devices]["header"]["time"] = str((endtime - starttime).seconds) + "秒" 119 | writeInfo(app, PATH("./info/info.pickle")) 120 | break 121 | # go.info[devices]["header"]["sumTime"] = str((endtime - starttime).seconds) + "秒" 122 | # report(go.info) 123 | if readInfo(PATH("./info/sumInfo.pickle")) <= 0: 124 | print(readInfo(PATH("./info/info.pickle"))) 125 | report(readInfo(PATH("./info/info.pickle"))) 126 | subprocess.Popen("taskkill /f /t /im adb.exe", shell=True) 127 | # shutil.rmtree((PATH("./info/"))) # 删除持久化目录 128 | 129 | 130 | # 开始脚本测试 131 | def start_monkey(cmd, log): 132 | # Monkey测试结果日志:monkey_log 133 | os.popen(cmd) 134 | print(cmd) 135 | 136 | # Monkey时手机日志,logcat 137 | logcatname = log + r"logcat.log" 138 | cmd2 = "adb logcat -d >%s" % (logcatname) 139 | os.popen(cmd2) 140 | 141 | # "导出traces文件" 142 | tracesname = log + r"traces.log" 143 | cmd3 = "adb shell cat /data/anr/traces.txt>%s" % tracesname 144 | os.popen(cmd3) 145 | 146 | def killport(): 147 | os.system(PATH('./kill5037.bat')) 148 | os.popen("adb kill-server adb") 149 | os.popen("adb start-server") 150 | if __name__ == '__main__': 151 | killport() 152 | time.sleep(1) 153 | runnerPool() 154 | -------------------------------------------------------------------------------- /report.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Louis-me/monkeyTest/1dc89a5f5765e1dcc2fd5bfb8e457ad37e014de6/report.xlsx --------------------------------------------------------------------------------