├── .DS_Store ├── .idea ├── MobilePerformance.iml ├── inspectionProfiles │ └── profiles_settings.xml ├── misc.xml ├── modules.xml └── workspace.xml ├── .project ├── .pydevproject ├── .settings └── org.eclipse.core.resources.prefs ├── Common ├── __init__.py ├── __init__.pyc ├── aapt ├── aapt.exe ├── const.py ├── const.pyc ├── userConf.py ├── userConf.pyc ├── util.py └── util.pyc ├── MainWindow.py ├── MainWindow.pyc ├── MakeGraph.jar ├── MonkeyTest ├── MonkeyTestProcess.py ├── MonkeyTestProcess.pyc ├── __init__.py ├── __init__.pyc ├── monkey.py ├── monkey.pyc ├── utils.py └── utils.pyc ├── Report ├── __init__.py ├── __init__.pyc ├── base.py ├── generateReport.py ├── generateReport.pyc ├── reportWritor.py └── reportWritor.pyc ├── ResMonitor ├── MemoryCPUMonitor.py ├── MemoryCPUMonitor.pyc ├── NetworkTraffic.py ├── NetworkTraffic.pyc ├── PowerMonitor.py ├── PowerMonitor.pyc ├── __init__.py └── __init__.pyc ├── StartTime ├── StartTime.py ├── StartTime.pyc ├── __init__.py └── __init__.pyc ├── logs └── .DS_Store ├── res └── logo.ico └── run.bat /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/.DS_Store -------------------------------------------------------------------------------- /.idea/MobilePerformance.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 11 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 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 | print 123 | 124 | 125 | 126 | 142 | 143 | 144 | 145 | 146 | true 147 | DEFINITION_ORDER 148 | 149 | 150 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 176 | 177 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 218 | 219 | 220 | 221 | 239 | 240 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 289 | 290 | 303 | 304 | 322 | 323 | 335 | 336 | project 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 371 | 372 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 399 | 400 | 401 | 402 | 1501770326396 403 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 436 | 437 | 439 | 440 | 441 | 442 | 443 | file://$PROJECT_DIR$/MonkeyTest/monkey.py 444 | 3 445 | 446 | 447 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 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 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 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 | 815 | 816 | 817 | 818 | 819 | 820 | 821 | 822 | 823 | 824 | 825 | 826 | 827 | 828 | 829 | 830 | 831 | 832 | 833 | 834 | 835 | 836 | 837 | 838 | 839 | 840 | 841 | 842 | 843 | 844 | 845 | 846 | 847 | 848 | 849 | 850 | 851 | 852 | 853 | 854 | 855 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | MobilePerformance 4 | 5 | 6 | 7 | 8 | 9 | org.python.pydev.PyDevBuilder 10 | 11 | 12 | 13 | 14 | 15 | org.python.pydev.pythonNature 16 | 17 | 18 | -------------------------------------------------------------------------------- /.pydevproject: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | /${PROJECT_DIR_NAME} 5 | 6 | python 2.7 7 | Default 8 | 9 | -------------------------------------------------------------------------------- /.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding//Common/const.py=UTF-8 3 | encoding//Common/util.py=UTF-8 4 | encoding//MonkeyTest/MonkeyTestProcess.py=utf-8 5 | encoding//MonkeyTest/monkey.py=utf-8 6 | encoding//MonkeyTest/utils.py=utf-8 7 | encoding//Report/base.py=UTF-8 8 | encoding//Report/generateReport.py=UTF-8 9 | encoding//Report/reportWritor.py=UTF-8 10 | encoding//ResMonitor/MemoryCPUMonitor.py=UTF-8 11 | encoding//ResMonitor/NetworkTraffic.py=UTF-8 12 | encoding//ResMonitor/PowerMonitor.py=UTF-8 13 | encoding//StartTime/StartTime.py=UTF-8 14 | encoding/MainWindow.py=UTF-8 15 | encoding/test.py=cp936 16 | -------------------------------------------------------------------------------- /Common/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/Common/__init__.py -------------------------------------------------------------------------------- /Common/__init__.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/Common/__init__.pyc -------------------------------------------------------------------------------- /Common/aapt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/Common/aapt -------------------------------------------------------------------------------- /Common/aapt.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/Common/aapt.exe -------------------------------------------------------------------------------- /Common/const.py: -------------------------------------------------------------------------------- 1 | #-*- coding: UTF-8 -*- 2 | ''' 3 | 4 | @author: zhaowei 5 | ''' 6 | import os 7 | 8 | workSpace = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) 9 | 10 | resPath = os.path.join(workSpace,"res") 11 | 12 | logPath = os.path.join(workSpace,"logs") 13 | 14 | jarFile = os.path.join(workSpace,"MakeGraph.jar") -------------------------------------------------------------------------------- /Common/const.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/Common/const.pyc -------------------------------------------------------------------------------- /Common/userConf.py: -------------------------------------------------------------------------------- 1 | #-*- coding: UTF-8 -*- 2 | ''' 3 | 4 | @author: zhaowei 5 | ''' 6 | class UserConf: 7 | packageName = "" 8 | activityName = "" -------------------------------------------------------------------------------- /Common/userConf.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/Common/userConf.pyc -------------------------------------------------------------------------------- /Common/util.py: -------------------------------------------------------------------------------- 1 | # -* - coding: UTF-8 -* - 2 | ''' 3 | 4 | @author: zhaowei 5 | ''' 6 | import os 7 | from Common import const 8 | from Common.userConf import UserConf 9 | 10 | def scan_devices(): 11 | "获取当前连接的设备" 12 | result = os.popen("adb devices").read() 13 | print result 14 | devices = result.split("\n")[1:] 15 | targets = [] 16 | for device in devices: 17 | if device.strip(): 18 | tmp = device.split() 19 | if len(tmp)==2 and tmp[1]=='device': 20 | deviceInfo = {} 21 | deviceID = tmp[0] 22 | deviceInfo['id'] = deviceID 23 | deviceInfo["os"] = os.popen("adb -s %s shell getprop ro.build.version.release" % (deviceID)).read().strip() 24 | deviceInfo["name"] = os.popen("adb -s %s shell getprop ro.product.model" % (deviceID)).read().strip().replace(" ", "-") 25 | 26 | targets.append(deviceInfo) 27 | return targets 28 | 29 | def getPackage(): 30 | "获取apk的包名和Activity的名字" 31 | apkFile = "" 32 | apkPath = os.path.join(const.workSpace, "apk") 33 | commonPath = os.path.join(const.workSpace, "Common") 34 | aapthPath = os.path.join(commonPath, "aapt") 35 | for filename in os.listdir(apkPath): 36 | if filename.endswith(".apk"): 37 | apkFile = os.path.join(apkPath,filename) 38 | break 39 | commonStr = aapthPath+" dump badging "+apkFile 40 | print commonStr 41 | result = os.popen(commonStr).read() 42 | lines = result.split("\n") 43 | 44 | for line in lines: 45 | if line.startswith("package: name="): 46 | UserConf.packageName = line.split()[1].split("=")[1][1:-1] 47 | break 48 | for line in lines: 49 | if line.startswith("launchable-activity: name="): 50 | UserConf.activityName = line.split()[1].split("=")[1][1:-1] 51 | break 52 | 53 | if __name__ == "__main__": 54 | getPackage() -------------------------------------------------------------------------------- /Common/util.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/Common/util.pyc -------------------------------------------------------------------------------- /MainWindow.py: -------------------------------------------------------------------------------- 1 | # -* - coding: UTF-8 -* - 2 | 3 | import time 4 | 5 | from Tkinter import * 6 | import os 7 | import tkMessageBox 8 | from ResMonitor.MemoryCPUMonitor import memoryCPUMonitor 9 | from ResMonitor.NetworkTraffic import networkTraffic 10 | from ResMonitor.PowerMonitor import powerMonitor 11 | from Common import util, const 12 | from MonkeyTest.MonkeyTestProcess import monkeyTestProcess 13 | from StartTime.StartTime import startTime 14 | import threading 15 | import traceback 16 | from Report.generateReport import generateReportEx 17 | from Common.userConf import UserConf 18 | 19 | class mainWindow(object): 20 | def __init__(self): 21 | self.root = Tk() 22 | self.cpuMonitor = None 23 | self.networkMonitor = None 24 | self.powerMonitor = None 25 | self.monkeyCheckVar = IntVar() 26 | self.startTimeCheckVar = IntVar() 27 | self.cpuCheckVar = IntVar() 28 | self.networkCheckVar = IntVar() 29 | self.powerCheckVar = IntVar() 30 | 31 | #设置窗口属性 32 | self.__initWindow() 33 | #初始化测试选项区域 34 | self.__initTestItem() 35 | #初始化资源监控选项区域 36 | self.__initResMonitor() 37 | #初始化窗口底部功能按钮区域 38 | self.__initButtonFrame() 39 | 40 | self.root.mainloop() 41 | 42 | 43 | def __initWindow(self): 44 | "初始化窗口设置,标题、大小、icon等" 45 | 46 | self.root.title("Android性能测试工具_BestTest") 47 | 48 | self.root.minsize(480, 350) 49 | #设置窗口在屏幕中央显示 50 | scnWidth,scnHeight = self.root.maxsize() 51 | tmpcnf = "480x350+%d+%d"%((scnWidth/2-240),(scnHeight/2-175)) 52 | self.root.wm_geometry(tmpcnf) 53 | 54 | self.root.iconbitmap(os.path.join(const.resPath,"logo.ico")) 55 | self.root.resizable(width=False, height=False) 56 | # self.root.设置背景图片 57 | 58 | 59 | def __initTestItem(self): 60 | "初始化测试项frame" 61 | self.frame_testItem = LabelFrame(self.root,text="测试项选择",width=430,height=90,font=('Arial', 15))#,padx=50,pady=30 62 | self.frame_testItem.grid(row=0,column=0,padx=20,pady=10,ipadx=3,ipady=3) 63 | self.frame_testItem.grid_propagate(0) # 使组件大小不变,此时width才起作用 64 | 65 | self.chb_monkey = Checkbutton(self.frame_testItem,text="monkey测试",font=('Arial', 12),variable = self.monkeyCheckVar, \ 66 | onvalue = 1, offvalue = 0,command = self.__monkeySetting) 67 | lb_time = Label(self.frame_testItem,text="执行时长:",font=('Arial', 12)) 68 | self.tb_time = Entry(self.frame_testItem,state=DISABLED) 69 | lb_minutes = Label(self.frame_testItem,text="分钟",font=('Arial', 12)) 70 | 71 | self.chb_startTime = Checkbutton(self.frame_testItem,text="启动时间测试",font=('Arial', 12),variable = self.startTimeCheckVar, \ 72 | onvalue = 1, offvalue = 0,command = self.__startTiemsSetting) 73 | lb_times = Label(self.frame_testItem,text="执行次数:",font=('Arial', 12)) 74 | self.tb_times = Entry(self.frame_testItem,state=DISABLED) 75 | lb_t = Label(self.frame_testItem,text="次",font=('Arial', 12)) 76 | 77 | 78 | self.chb_monkey.grid(row=0, column=0,sticky=W) 79 | lb_time.grid(row=0, column=1) 80 | self.tb_time.grid(row=0, column=2) 81 | lb_minutes.grid(row=0, column=3) 82 | 83 | self.chb_startTime.grid(row=1, column=0,sticky=W) 84 | lb_times.grid(row=1, column=1) 85 | self.tb_times.grid(row=1, column=2) 86 | lb_t.grid(row=1, column=3) 87 | 88 | 89 | 90 | 91 | def __initResMonitor(self): 92 | "初始化资源监控frame" 93 | self.fram_resmonitor = LabelFrame(self.root,text="资源监控设置",width=430,height=120,font=('Arial', 15))#,padx=50,pady=30 94 | self.fram_resmonitor.grid(row=1,column=0,sticky=W,padx=20,pady=10,ipadx=3,ipady=3) 95 | self.fram_resmonitor.grid_propagate(0)#保障frame的尺寸设置生效 96 | 97 | self.chb_cpu = Checkbutton(self.fram_resmonitor,text="cpu、内存资源",font=('Arial', 12),variable = self.cpuCheckVar, \ 98 | onvalue = 1, offvalue = 0) 99 | self.chb_network = Checkbutton(self.fram_resmonitor,text="流量监控",font=('Arial', 12),variable = self.networkCheckVar, \ 100 | onvalue = 1, offvalue = 0) 101 | self.chb_power = Checkbutton(self.fram_resmonitor,text="电量监控",font=('Arial', 12),variable = self.powerCheckVar, \ 102 | onvalue = 1, offvalue = 0,state=DISABLED) 103 | 104 | self.chb_cpu.grid(row=0,column=0,sticky=W) 105 | self.chb_network.grid(row=1,column=0,sticky=W) 106 | self.chb_power.grid(row=2,column=0,sticky=W) 107 | 108 | def __initButtonFrame(self): 109 | "初始化底部功能按钮frame" 110 | self.frame_btns = Frame(self.root) 111 | self.frame_btns.grid(row=2,column=0,pady=40) 112 | 113 | self.btn_scanDevices = Button(self.frame_btns,text="设备检测",width=8,font=('Arial', 12),command = self.scanDevices) 114 | self.btn_start = Button(self.frame_btns,text="开始",width=8,font=('Arial', 12),command = self.start) 115 | self.btn_end = Button(self.frame_btns,text="结束",width=8,font=('Arial', 12),command = self.terminate)#,state=DISABLED 116 | self.btn_quit = Button(self.frame_btns,text="退出",width=8,bg = 'red',font=('Arial', 12),command = self.quit) 117 | 118 | self.btn_scanDevices.grid(row=0,column=0) 119 | self.btn_start.grid(row=0,column=1) 120 | self.btn_end.grid(row=0,column=2) 121 | self.btn_quit.grid(row=0,column=3) 122 | 123 | def __monkeySetting(self): 124 | "实现时长输入框的禁用与启用" 125 | if self.monkeyCheckVar.get() == 1: 126 | self.tb_time['state'] = NORMAL 127 | self.tb_time.focus() 128 | else: 129 | self.tb_time['state'] = DISABLED 130 | 131 | def __startTiemsSetting(self): 132 | "实现次数输入框的禁用与启用" 133 | if self.startTimeCheckVar.get() == 1: 134 | self.tb_times['state'] = NORMAL 135 | self.tb_times.focus_set() 136 | else: 137 | self.tb_times['state'] = DISABLED 138 | 139 | def quit(self): 140 | "关闭窗口,退出程序" 141 | self.root.quit() 142 | 143 | def scanDevices(self): 144 | "扫描手机设备" 145 | devices = util.scan_devices() 146 | if len(devices)>0: 147 | msg = "当前连接设备:" 148 | for d in devices: 149 | msg += "%s%s"%(os.linesep,str(d).replace("'", "")) 150 | tkMessageBox.showinfo("提示", msg) 151 | else: 152 | tkMessageBox.showwarning("警示", "未连接手机设备,请检查!") 153 | 154 | 155 | def start(self): 156 | "开始执行测试" 157 | self.resultDict = {} 158 | #设备检测 159 | devices = util.scan_devices() 160 | 161 | if len(devices)<=0: 162 | tkMessageBox.showwarning("警示", "未连接手机设备,请检查!") 163 | return 164 | deviceID= devices[0]['id'] 165 | #获取包名 166 | util.getPackage() 167 | if UserConf.packageName=="": 168 | tkMessageBox.showwarning("警示", "包名获取失败,请将apk文件放到工程目录下的apk目录下,文件以.apk结尾") 169 | return 170 | if UserConf.activityName=="": 171 | tkMessageBox.showwarning("警示","ActivityName获取失败,请将apk文件放到工程目录下的apk目录下,文件以.apk结尾") 172 | return 173 | print "PackageName: "+UserConf.packageName 174 | print "ActivityName: "+UserConf.activityName 175 | #资源勾选检测 176 | if self.cpuCheckVar.get() == 0 and self.networkCheckVar.get()==0 and self.powerCheckVar.get() == 0: 177 | tkMessageBox.showwarning("警示", "未选中任何资源监控,请至少选择一项!") 178 | return 179 | #monkey测试检查 180 | if self.monkeyCheckVar.get() == 1 and self.tb_time.get() == "": 181 | tkMessageBox.showerror("提示", "请输入monkey执行时间!") 182 | return 183 | #启动时间测试检查 184 | if self.startTimeCheckVar.get() == 1 and self.tb_times.get() == "": 185 | tkMessageBox.showerror("提示", "请输入启动时间得测试次数!") 186 | return 187 | 188 | if self.monkeyCheckVar.get() == 0 and self.startTimeCheckVar.get()==0: 189 | tkMessageBox.showinfo("提示", "未选中任何测试项,所以,您必须亲自在手机上点点点了~") 190 | self.resultDict["startTime"] = time.strftime("%Y/%m/%d %H:%M:%S") 191 | 192 | #创建文件夹 193 | self.resultFolder = os.path.join(const.logPath,"task_%s"%time.strftime("%m%d%H%M%S")) 194 | if not os.path.exists(self.resultFolder): 195 | os.mkdir(self.resultFolder) 196 | 197 | 198 | #开启资源监控器 199 | if self.cpuCheckVar.get() == 1: 200 | self.cpuMonitor = memoryCPUMonitor(logFolder=self.resultFolder,packageName=UserConf.packageName) 201 | self.cpuMonitor.start() 202 | 203 | if self.networkCheckVar.get() == 1: 204 | self.networkMonitor = networkTraffic(self.resultFolder,deviceID) 205 | self.networkMonitor.start() 206 | 207 | if self.powerCheckVar.get() == 1: 208 | self.powerMonitor = powerMonitor(logFolder=self.resultFolder) 209 | self.powerMonitor.start() 210 | 211 | if self.monkeyCheckVar.get() == 1 or self.startTimeCheckVar.get() == 1: 212 | try: 213 | itemList = [] 214 | monkeyTime = 0 215 | times = 0 216 | 217 | if self.monkeyCheckVar.get() == 1: 218 | itemList.append("monkeytest") 219 | monkeyTime = int(self.tb_time.get()) 220 | if self.startTimeCheckVar.get() == 1: 221 | itemList.append("starttimetest") 222 | times = int(self.tb_times.get()) 223 | 224 | taskT = taskThread(itemList,self.resultFolder,deviceID,times,monkeyTime) 225 | taskT.start() 226 | except Exception: 227 | print traceback.format_exc() 228 | else: 229 | print "手动执行".decode("utf-8") 230 | 231 | def terminate(self): 232 | "停止测试" 233 | tkMessageBox.showwarning("警示", "您已停止测试,请稍后查看结果!") 234 | self.btn_start['state'] = ACTIVE 235 | 236 | powerMonitor.terminate() 237 | memoryCPUMonitor.terminate() 238 | networkTraffic.terminate() 239 | time.sleep(30)#需要等待制图结束 240 | self.resultDict["endTime"] = time.strftime("%Y/%m/%d %H:%M:%S") 241 | stime = time.mktime(time.strptime(self.resultDict["startTime"],'%Y/%m/%d %H:%M:%S')) 242 | etime = time.mktime(time.strptime(self.resultDict["endTime"],'%Y/%m/%d %H:%M:%S')) 243 | utime = etime - stime 244 | self.resultDict["useTime"] = str(utime) 245 | self.resultDict["testItems"] = {} 246 | generateReportEx(self.resultDict,self.resultFolder) 247 | # tkMessageBox.showinfo("提示", "报告已生成。请到文件夹%s下查看。"%self.resultFolder) 248 | 249 | 250 | class taskThread(threading.Thread): 251 | def __init__(self,itemList,path,deviceID,startTimes=0,monkeyTime=0): 252 | threading.Thread.__init__(self) 253 | self.itemList = itemList 254 | self.path = path 255 | self.deviceID = deviceID 256 | self.startTimes = startTimes 257 | self.monkeyTime = monkeyTime 258 | 259 | 260 | def run(self): 261 | resultDict = {} 262 | resultDict["startTime"] = time.strftime("%Y/%m/%d %H:%M:%S") 263 | tmp = {} 264 | try: 265 | for item in self.itemList: 266 | if item == "monkeytest": 267 | "执行monkey测试" 268 | monkeyTest = monkeyTestProcess(self.deviceID,UserConf.packageName,self.path,self.monkeyTime) 269 | r1 = monkeyTest.execute() 270 | tmp["monkeyTest"] = r1 271 | if item == "starttimetest": 272 | "执行启动时间测试" 273 | self.startTest = startTime(self.startTimes,UserConf.packageName,UserConf.activityName) 274 | r2 = self.startTest.execute() 275 | tmp["startTime"] = r2 276 | except Exception: 277 | print traceback.format_exc() 278 | finally: 279 | powerMonitor.terminate() 280 | memoryCPUMonitor.terminate() 281 | networkTraffic.terminate() 282 | resultDict["testItems"] = tmp 283 | resultDict["endTime"] = time.strftime("%Y/%m/%d %H:%M:%S") 284 | stime = time.mktime(time.strptime(resultDict["startTime"],'%Y/%m/%d %H:%M:%S')) 285 | etime = time.mktime(time.strptime(resultDict["endTime"],'%Y/%m/%d %H:%M:%S')) 286 | utime = etime - stime 287 | resultDict["useTime"] = str(utime) 288 | time.sleep(30)#需要等待制图结束 289 | generateReportEx(resultDict,self.path) 290 | 291 | 292 | if __name__ == "__main__": 293 | m = mainWindow() -------------------------------------------------------------------------------- /MainWindow.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/MainWindow.pyc -------------------------------------------------------------------------------- /MakeGraph.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/MakeGraph.jar -------------------------------------------------------------------------------- /MonkeyTest/MonkeyTestProcess.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | ''' 3 | 4 | @author: zhaowei 5 | ''' 6 | from threading import Thread 7 | import os 8 | import platform 9 | import time 10 | import datetime 11 | import traceback 12 | from monkey import Monkey 13 | import utils 14 | 15 | def getCurrentTime(): 16 | return time.strftime("%m%d%H%M%S") 17 | 18 | class MonkeyThread(Thread): 19 | def __init__(self, logPath,device_id, pkgName): 20 | Thread.__init__(self) 21 | 22 | self.monkeyInstance = Monkey(logPath,device_id,pkgName) 23 | self.logPath = logPath 24 | 25 | 26 | def run(self): 27 | self.monkeyInstance.startMonkey() 28 | 29 | 30 | class monkeyTestProcess(object): 31 | 32 | def __init__(self, device_id, pkgName, log_path, minutes): 33 | self.pkgName = pkgName 34 | self.minutes = minutes 35 | 36 | self.crashCount = 0 37 | self.anrCount = 0 38 | 39 | self.crashInfo = [] 40 | self.anrInfo = [] 41 | 42 | self.tasksCrashCount = 0 43 | self.tasksAnrCount = 0 44 | 45 | print("StabilityTask-log_path is %s"%(log_path)) 46 | self.logPath = log_path 47 | self.monkeyLogPath = os.path.join(self.logPath, "monkey.log") 48 | 49 | self.deviceId = device_id 50 | self.tasks = {} 51 | self.tasks["pkgName"] = self.pkgName 52 | self.tasks["duration"] = self.minutes 53 | self.tasks["deviceID"] = device_id 54 | 55 | 56 | def crash_analyse(self,crashCount): 57 | 58 | f = open(self.monkeyLogPath,'r') # 返回一个文件对象 59 | line = f.readline() # 调用文件的 readline()方法 60 | flag = 1 61 | for i in range(0, int(crashCount)): 62 | result = '' 63 | while line: 64 | if flag == 1: 65 | if not line.find('CRASH') == -1: 66 | result += line 67 | flag = 0 68 | else: 69 | if not line.find('//') == -1: 70 | if not line.find('CRASH') == -1: 71 | flag = 1 72 | break 73 | else: 74 | result += line 75 | else: 76 | flag = 1 77 | break 78 | line = f.readline() 79 | 80 | self.crashInfo.append(result) 81 | 82 | f.close() 83 | 84 | 85 | def anr_analyse(self,anrCount): 86 | f = open(self.monkeyLogPath,'r') # 返回一个文件对象 87 | line = f.readline() # 调用文件的 readline()方法 88 | flag = 1 89 | for i in range(0, int(anrCount)): 90 | result = '' 91 | while line: 92 | if flag == 1: 93 | if not line.find('NOT RESPONDING') == -1: 94 | result += line 95 | flag = 0 96 | else: 97 | if not line.find('anr traces status was 0') == -1: 98 | flag = 1 99 | break 100 | else: 101 | result += line 102 | line = f.readline() 103 | 104 | self.anrInfo.append(result) 105 | 106 | f.close() 107 | 108 | 109 | def analyse(self): 110 | 111 | if platform.system() == "Windows": 112 | crashCount = os.popen('type %s|find "CRASH:" /c'%(self.monkeyLogPath,)).read().strip() 113 | anrCount = os.popen('type %s|find "ANR " /c'%(self.monkeyLogPath,)).read().strip() 114 | else: 115 | crashCount = os.popen('grep -c "CRASH:" %s'%(self.monkeyLogPath,)).read().strip() 116 | anrCount = os.popen('grep -c "ANR " %s'%(self.monkeyLogPath,)).read().strip() 117 | 118 | self.crash_analyse(crashCount) 119 | self.anr_analyse(anrCount) 120 | 121 | self.tasksCrashCount = int(crashCount) 122 | self.tasksAnrCount = int(anrCount) 123 | 124 | def collect(self): 125 | utils.getLog(self.logPath,self.deviceId) 126 | utils.getTraceData(self.logPath,self.deviceId) 127 | 128 | def execute(self): 129 | 130 | startTime = time.time() 131 | print("monkey开始时间:%s"%(datetime.datetime.now())).decode("utf-8") 132 | monkeyThreadInstance = MonkeyThread(self.logPath,self.deviceId,self.pkgName) 133 | utils.forceStop(self.pkgName,self.deviceId) 134 | if not os.path.exists(self.logPath): 135 | os.makedirs(self.logPath) 136 | 137 | try: 138 | monkeyThreadInstance.start() 139 | 140 | while True: 141 | endTime = time.time() 142 | # 清除之前的日志 143 | # utils.clearLog(self.deviceId) 144 | 145 | if (endTime-startTime) < self.minutes*60: 146 | if monkeyThreadInstance.is_alive(): 147 | time.sleep(10) 148 | else: 149 | utils.forceStop(self.pkgName,self.deviceId) 150 | if not os.path.exists(self.logPath): 151 | os.makedirs(self.logPath) 152 | 153 | monkeyThreadInstance = MonkeyThread(self.deviceId,self.pkgName) 154 | monkeyThreadInstance.start() 155 | else: 156 | print("monkey结束时间:%s"%(datetime.datetime.now())).decode("utf-8") 157 | Monkey.terminateMonkey(self.deviceId) 158 | 159 | self.collect() 160 | self.analyse() 161 | break 162 | except Exception,e: 163 | print("Monkey Exception:"%(e)) 164 | print("Monkey traceback:"%(traceback.print_exc())) 165 | traceback.print_exc() 166 | Monkey.terminateMonkey(self.deviceId) 167 | self.collect() 168 | self.analyse() 169 | 170 | finally: 171 | 172 | self.tasks['crashCount'] = str(self.tasksCrashCount) 173 | if self.tasksCrashCount != 0: 174 | self.tasks['crashInfo'] = self.crashInfo 175 | 176 | self.tasks["anrCount"] = str(self.tasksAnrCount) 177 | 178 | if self.tasksAnrCount != 0: 179 | self.tasks['anrInfo'] = self.anrInfo 180 | 181 | print self.tasks 182 | return self.tasks 183 | 184 | if __name__ == "__main__": 185 | result = monkeyTestProcess("", "", r'd:/test/logs', 1).start() 186 | -------------------------------------------------------------------------------- /MonkeyTest/MonkeyTestProcess.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/MonkeyTest/MonkeyTestProcess.pyc -------------------------------------------------------------------------------- /MonkeyTest/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/MonkeyTest/__init__.py -------------------------------------------------------------------------------- /MonkeyTest/__init__.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/MonkeyTest/__init__.pyc -------------------------------------------------------------------------------- /MonkeyTest/monkey.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | 3 | 4 | import os 5 | from random import randint 6 | import time 7 | 8 | 9 | class Monkey(object): 10 | def __init__(self, logpath,device_id,pkgName): 11 | self.proName = "com.android.commands.monkey" 12 | 13 | self.logPath = logpath 14 | self.proportion = 100 15 | self.pkgName = pkgName 16 | self.device_id = device_id 17 | 18 | self.throttle = 500 #间隔时间,单位:毫秒 19 | self.runNum = 50000 #monkey动作次数 20 | 21 | '''动作选项说明 22 | --pct-touch:指定触摸事件的百分比, 23 | --pct-motion (滑动事件)、 24 | --pct-trackball (轨迹球事件) 、 25 | --pct-nav (导航事件 up/down/left/right)、 26 | --pct-majornav (主要导航事件 back key 、 menu key)、 27 | --pct-syskeys (系统按键事件 Home 、Back 、startCall 、 endCall 、 volumeControl)、 28 | --pct-appswitch (activity之间的切换)、 29 | --pct-anyevent (任意事件) 30 | ''' 31 | #动作百分比配置,合计100% 32 | self.events = {"--pct-touch":35, "--pct-motion":15, "--pct-trackball":15,"--pct-nav":7,"--pct-majornav":8, 33 | "--pct-syskeys":10,"--pct-appswitch":5, "--pct-anyevent":5,"--pct-flip":0} 34 | 35 | 36 | def generateEventStr(self): 37 | "生成action字符串" 38 | eventStr = "" 39 | for key in self.events: 40 | eventStr = eventStr + " %s %s"%(key, self.events[key]) 41 | return eventStr 42 | 43 | def generateCommand(self): 44 | "生成monkey命令行" 45 | seed = randint(100000000000, 200000000000)#随机事件种子值 46 | 47 | command = "adb -s %s shell monkey -p %s -s %d -v --throttle %s %s --ignore-crashes --ignore-timeouts\ 48 | --ignore-security-exceptions --ignore-native-crashes --monitor-native-crashes "%(self.device_id,self.pkgName, seed, self.throttle, self.generateEventStr()) 49 | 50 | command = command + str(self.runNum) 51 | return command 52 | 53 | @staticmethod 54 | def terminateMonkey(deviceID): 55 | def getMonekyPid(): 56 | top = os.popen("adb -s %s shell top -n 1"%deviceID).read() 57 | for topItem in top.split("\n"): 58 | if "com.android.commands.monkey" in topItem: 59 | return topItem.split()[0] 60 | pid = getMonekyPid() 61 | while pid: 62 | os.system("adb -s %s shell kill -9 %s"%(deviceID,pid)) 63 | pid = getMonekyPid() 64 | 65 | def startMonkey(self): 66 | command = self.generateCommand() 67 | print(command) 68 | os.system("%s >> %s"%(command, os.path.join(self.logPath, "monkey.log"))) 69 | -------------------------------------------------------------------------------- /MonkeyTest/monkey.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/MonkeyTest/monkey.pyc -------------------------------------------------------------------------------- /MonkeyTest/utils.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | 3 | import os 4 | import zipfile 5 | 6 | 7 | def clearLog(deviceID): 8 | os.system("adb -s %s shell logcat -c"%deviceID) 9 | 10 | def getLog(logPath,deviceID): 11 | logcatPath = os.path.join(logPath, "logcat.log") 12 | os.system("adb -s %s shell logcat -d > %s"%(deviceID,logcatPath)) 13 | 14 | def dumpState(logPath,deviceID): 15 | dumpStateLogPath = os.path.join(logPath, "dumpState.log") 16 | os.system("adb -s %s shell dumpstate > %s"%(deviceID,dumpStateLogPath)) 17 | 18 | def getTraceData(logPath,deviceID): 19 | os.system("adb -s %s pull /data/anr %s"%(deviceID,logPath)) 20 | 21 | #可能获取到多个设备 22 | def getDeviceInfo(): 23 | return os.popen("adb shell getprop ro.build.fingerprint").read().strip() 24 | 25 | def compressFolder(folderPath): 26 | 27 | f = zipfile.ZipFile('abc.zip', 'w') 28 | for item in os.listdir(folderPath): 29 | f.write(os.path.join(folderPath, item)) 30 | f.close() 31 | 32 | def forceStop(packageName,deviceID): 33 | os.system("adb -s %s shell am force-stop %s"%(deviceID,packageName)) 34 | cmd1 = 'adb -s %s shell ps | grep %s'%(deviceID,packageName) 35 | cmd2 = 'adb -s %s shell ps | find %s'%(deviceID,packageName) 36 | result = os.popen(cmd1).read() 37 | if result is None or result == "": 38 | result = os.popen(cmd2).read() 39 | if result is not None and result != "": 40 | lines = result.split("\n") 41 | for i in xrange(len(lines)): 42 | infos = lines[i].split() 43 | if infos[8]==packageName: 44 | pid = infos[1] 45 | break 46 | os.system('adb -s %s shell su -c "kill -9 %s"'%(deviceID,pid)) 47 | 48 | def reboot(deviceID=None): 49 | if deviceID is None: 50 | os.system("adb reboot") 51 | else: 52 | os.system("adb -s %s reboot"%deviceID) 53 | 54 | -------------------------------------------------------------------------------- /MonkeyTest/utils.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/MonkeyTest/utils.pyc -------------------------------------------------------------------------------- /Report/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/Report/__init__.py -------------------------------------------------------------------------------- /Report/__init__.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/Report/__init__.pyc -------------------------------------------------------------------------------- /Report/base.py: -------------------------------------------------------------------------------- 1 | # -* - coding: UTF-8 -* - 2 | 3 | import re 4 | import operator 5 | import ast 6 | 7 | VAR_FRAGMENT = 0 8 | OPEN_BLOCK_FRAGMENT = 1 9 | CLOSE_BLOCK_FRAGMENT = 2 10 | TEXT_FRAGMENT = 3 11 | 12 | VAR_TOKEN_START = '{{' 13 | VAR_TOKEN_END = '}}' 14 | BLOCK_TOKEN_START = '{%' 15 | BLOCK_TOKEN_END = '%}' 16 | 17 | TOK_REGEX = re.compile(r"(%s.*?%s|%s.*?%s)" % ( 18 | VAR_TOKEN_START, 19 | VAR_TOKEN_END, 20 | BLOCK_TOKEN_START, 21 | BLOCK_TOKEN_END 22 | )) 23 | 24 | WHITESPACE = re.compile('\s+') 25 | 26 | operator_lookup_table = { 27 | '<': operator.lt, 28 | '>': operator.gt, 29 | '==': operator.eq, 30 | '!=': operator.ne, 31 | '<=': operator.le, 32 | '>=': operator.ge 33 | } 34 | 35 | 36 | class TemplateError(Exception): 37 | pass 38 | 39 | 40 | class TemplateContextError(TemplateError): 41 | 42 | def __init__(self, context_var): 43 | self.context_var = context_var 44 | 45 | def __str__(self): 46 | return "cannot resolve '%s'" % self.context_var 47 | 48 | 49 | class TemplateSyntaxError(TemplateError): 50 | 51 | def __init__(self, error_syntax): 52 | self.error_syntax = error_syntax 53 | 54 | def __str__(self): 55 | return "'%s' seems like invalid syntax" % self.error_syntax 56 | 57 | 58 | def eval_expression(expr): 59 | try: 60 | return 'literal', ast.literal_eval(expr) 61 | except ValueError, SyntaxError: 62 | return 'name', expr 63 | 64 | 65 | def resolve(name, context): 66 | if name.startswith('..'): 67 | context = context.get('..', {}) 68 | name = name[2:] 69 | try: 70 | for tok in name.split('.'): 71 | context = context[tok] 72 | return context 73 | except KeyError: 74 | raise TemplateContextError(name) 75 | 76 | 77 | class _Fragment(object): 78 | def __init__(self, raw_text): 79 | self.raw = raw_text 80 | self.clean = self.clean_fragment() 81 | 82 | def clean_fragment(self): 83 | if self.raw[:2] in (VAR_TOKEN_START, BLOCK_TOKEN_START): 84 | return self.raw.strip()[2:-2].strip() 85 | return self.raw 86 | 87 | @property 88 | def type(self): 89 | raw_start = self.raw[:2] 90 | if raw_start == VAR_TOKEN_START: 91 | return VAR_FRAGMENT 92 | elif raw_start == BLOCK_TOKEN_START: 93 | return CLOSE_BLOCK_FRAGMENT if self.clean[:3] == 'end' else OPEN_BLOCK_FRAGMENT 94 | else: 95 | return TEXT_FRAGMENT 96 | 97 | 98 | class _Node(object): 99 | creates_scope = False 100 | 101 | def __init__(self, fragment=None): 102 | self.children = [] 103 | self.process_fragment(fragment) 104 | 105 | def process_fragment(self, fragment): 106 | pass 107 | 108 | def enter_scope(self): 109 | pass 110 | 111 | def render(self, context): 112 | pass 113 | 114 | def exit_scope(self): 115 | pass 116 | 117 | def render_children(self, context, children=None): 118 | if children is None: 119 | children = self.children 120 | def render_child(child): 121 | child_html = child.render(context) 122 | return '' if not child_html else str(child_html) 123 | return ''.join(map(render_child, children)) 124 | 125 | 126 | class _ScopableNode(_Node): 127 | creates_scope = True 128 | 129 | class _Root(_Node): 130 | def render(self, context): 131 | return self.render_children(context) 132 | 133 | 134 | class _Variable(_Node): 135 | def process_fragment(self, fragment): 136 | self.name = fragment 137 | 138 | def render(self, context): 139 | return resolve(self.name, context) 140 | 141 | 142 | class _Each(_ScopableNode): 143 | def process_fragment(self, fragment): 144 | try: 145 | _, it = WHITESPACE.split(fragment, 1) 146 | self.it = eval_expression(it) 147 | except ValueError: 148 | raise TemplateSyntaxError(fragment) 149 | 150 | def render(self, context): 151 | items = self.it[1] if self.it[0] == 'literal' else resolve(self.it[1], context) 152 | def render_item(item): 153 | return self.render_children({'..': context, 'it': item}) 154 | return ''.join(map(render_item, items)) 155 | 156 | 157 | class _If(_ScopableNode): 158 | def process_fragment(self, fragment): 159 | bits = fragment.split()[1:] 160 | if len(bits) not in (1, 3): 161 | raise TemplateSyntaxError(fragment) 162 | self.lhs = eval_expression(bits[0]) 163 | if len(bits) == 3: 164 | self.op = bits[1] 165 | self.rhs = eval_expression(bits[2]) 166 | 167 | def render(self, context): 168 | lhs = self.resolve_side(self.lhs, context) 169 | if hasattr(self, 'op'): 170 | op = operator_lookup_table.get(self.op) 171 | if op is None: 172 | raise TemplateSyntaxError(self.op) 173 | rhs = self.resolve_side(self.rhs, context) 174 | exec_if_branch = op(lhs, rhs) 175 | else: 176 | exec_if_branch = operator.truth(lhs) 177 | if_branch, else_branch = self.split_children() 178 | return self.render_children(context, 179 | self.if_branch if exec_if_branch else self.else_branch) 180 | 181 | def resolve_side(self, side, context): 182 | return side[1] if side[0] == 'literal' else resolve(side[1], context) 183 | 184 | def exit_scope(self): 185 | self.if_branch, self.else_branch = self.split_children() 186 | 187 | def split_children(self): 188 | if_branch, else_branch = [], [] 189 | curr = if_branch 190 | for child in self.children: 191 | if isinstance(child, _Else): 192 | curr = else_branch 193 | continue 194 | curr.append(child) 195 | return if_branch, else_branch 196 | 197 | 198 | class _Else(_Node): 199 | def render(self, context): 200 | pass 201 | 202 | 203 | class _Call(_Node): 204 | def process_fragment(self, fragment): 205 | try: 206 | bits = WHITESPACE.split(fragment) 207 | self.callable = bits[1] 208 | self.args, self.kwargs = self._parse_params(bits[2:]) 209 | except ValueError, IndexError: 210 | raise TemplateSyntaxError(fragment) 211 | 212 | def _parse_params(self, params): 213 | args, kwargs = [], {} 214 | for param in params: 215 | if '=' in param: 216 | name, value = param.split('=') 217 | kwargs[name] = eval_expression(value) 218 | else: 219 | args.append(eval_expression(param)) 220 | return args, kwargs 221 | 222 | def render(self, context): 223 | resolved_args, resolved_kwargs = [], {} 224 | for kind, value in self.args: 225 | if kind == 'name': 226 | value = resolve(value, context) 227 | resolved_args.append(value) 228 | for key, (kind, value) in self.kwargs.iteritems(): 229 | if kind == 'name': 230 | value = resolve(value, context) 231 | resolved_kwargs[key] = value 232 | resolved_callable = resolve(self.callable, context) 233 | if hasattr(resolved_callable, '__call__'): 234 | return resolved_callable(*resolved_args, **resolved_kwargs) 235 | else: 236 | raise TemplateError("'%s' is not a callable" % self.callable) 237 | 238 | 239 | class _Text(_Node): 240 | def process_fragment(self, fragment): 241 | self.text = fragment 242 | 243 | def render(self, context): 244 | return self.text 245 | 246 | 247 | class Compiler(object): 248 | def __init__(self, template_string): 249 | self.template_string = template_string 250 | 251 | def each_fragment(self): 252 | for fragment in TOK_REGEX.split(self.template_string): 253 | if fragment: 254 | yield _Fragment(fragment) 255 | 256 | def compile(self): 257 | root = _Root() 258 | scope_stack = [root] 259 | for fragment in self.each_fragment(): 260 | if not scope_stack: 261 | raise TemplateError('nesting issues') 262 | parent_scope = scope_stack[-1] 263 | if fragment.type == CLOSE_BLOCK_FRAGMENT: 264 | parent_scope.exit_scope() 265 | scope_stack.pop() 266 | continue 267 | new_node = self.create_node(fragment) 268 | if new_node: 269 | parent_scope.children.append(new_node) 270 | if new_node.creates_scope: 271 | scope_stack.append(new_node) 272 | new_node.enter_scope() 273 | return root 274 | 275 | def create_node(self, fragment): 276 | node_class = None 277 | if fragment.type == TEXT_FRAGMENT: 278 | node_class = _Text 279 | elif fragment.type == VAR_FRAGMENT: 280 | node_class = _Variable 281 | elif fragment.type == OPEN_BLOCK_FRAGMENT: 282 | cmd = fragment.clean.split()[0] 283 | if cmd == 'each': 284 | node_class = _Each 285 | elif cmd == 'if': 286 | node_class = _If 287 | elif cmd == 'else': 288 | node_class = _Else 289 | elif cmd == 'call': 290 | node_class = _Call 291 | if node_class is None: 292 | raise TemplateSyntaxError(fragment) 293 | return node_class(fragment.clean) 294 | 295 | 296 | class Template(object): 297 | def __init__(self, contents): 298 | self.contents = contents 299 | self.root = Compiler(contents).compile() 300 | 301 | def render(self, **kwargs): 302 | return self.root.render(kwargs) 303 | -------------------------------------------------------------------------------- /Report/generateReport.py: -------------------------------------------------------------------------------- 1 | # -* - coding: UTF-8 -* - 2 | 3 | import os 4 | from Report import reportWritor 5 | import time 6 | from ResMonitor.NetworkTraffic import networkTraffic 7 | 8 | 9 | report_dir = os.path.join(os.path.dirname(__file__), 'results') 10 | report_dir = "D:/eclipse/workspace/MobilePerformance/logs/task_0304113023" 11 | 12 | 13 | def formatStr1(d): 14 | "{'duration': 2, 'crashCount': '0', 'anrCount': '0', 'pkgName': '', 'deviceID': 'HC52SWME0349'}" 15 | 16 | s = "此次测试时长%d分钟,测试设备ID%s,其中crash数量%d个,ANR数量%d个。"%(d["duration"],d["deviceID"],int(d['crashCount']),int(d['anrCount'])) 17 | return s 18 | 19 | def formatStr2(d): 20 | "{'count': 10, 'max': 2369ms, 'avg': 1929ms, 'min': 1802ms}" 21 | s = "此次测试共执行%d次,其中最大时间为 %d ms,最小时间为 %d ms,平均时间(取出最大值和最小值)为 %d ms"%(d['count'],int(d['max']),int(d['min']),int(d['avg'])) 22 | return s 23 | 24 | 25 | def getAvgCpuAndMemory(log_dir): 26 | memory_log_dir = os.path.join(log_dir,'memory.log') 27 | #"C:\\Users\\zhaowei\\workspace\\MobilePerformance\\logs\\task_0906144920\\memory.log" 28 | f = open(memory_log_dir, "r") 29 | cpuDatas=[] 30 | memDatas=[] 31 | for line in f: 32 | if line.strip(): 33 | ss = line.split() 34 | index = 2 35 | for i in range(len(ss)): 36 | if "%" in ss[i]: 37 | index = i 38 | break 39 | cpuDatas.append(int(ss[index][0:-1])) 40 | memDatas.append(int(ss[index+4][0:-1])) 41 | cpuDatas.sort() 42 | memDatas.sort() 43 | cpus = cpuDatas[1:-1] 44 | memorys = memDatas[1:-1] 45 | avgCpu = round(float(sum(cpus))/len(cpus),2) 46 | avgMem = round(float(sum(memorys))/len(memorys)/1024,2) 47 | return [avgCpu,avgMem] 48 | 49 | 50 | def generateReportEx(resultDict,report_dir): 51 | "生成报告" 52 | "resultList-测试结果数据" 53 | 54 | # resultDict = {'testItems': {'startTime': {'count': 3, 'max': 1877L, 'avg': 1839L, 'min': 1781L}}, 'endTime': '2016/03/04 14:42:27', 'startTime': '2016/03/04 14:42:11'} 55 | start_time = resultDict["startTime"] 56 | end_time = resultDict["endTime"] 57 | use_time = resultDict["useTime"] 58 | avgCpuAndMem = getAvgCpuAndMemory(report_dir) 59 | monkeyResult = None 60 | startTimeResult = None 61 | 62 | if resultDict["testItems"].has_key("monkeyTest"): 63 | monkeyResult = resultDict["testItems"]["monkeyTest"] 64 | if resultDict["testItems"].has_key("startTime"): 65 | startTimeResult = resultDict["testItems"]["startTime"] 66 | 67 | testItemStr = "测试内容包括:" 68 | if len(resultDict["testItems"]) == 0: 69 | testItemStr += "手工操作。" 70 | else: 71 | testItemStr += ",".join(resultDict["testItems"].keys()) 72 | testItemStr = testItemStr.replace("monkeyTest", "monkey测试") 73 | testItemStr = testItemStr.replace("startTime", "启动时间测试") 74 | 75 | 76 | report = reportWritor.Report(report_dir) 77 | 78 | #测试结果总结部分--begin 79 | report.write_line('
') 80 | report.write_line('

Hi,all:

本次测试完成,测试开始时间:%s,结束时间:%s,共计:%s秒。%s。

'%(start_time,end_time,use_time,testItemStr)) 81 | report.write_line('
') 82 | #测试结果总结部分--end 83 | 84 | #测试结果详细部分--begin 85 | 86 | #Monkey测试部分 87 | if monkeyResult is not None: 88 | report.write_line('
') 89 | report.write_line('

Monkey测试结果:
%s

'%formatStr1(monkeyResult)) 90 | report.write_line('
') 91 | #启动时间部分 92 | if startTimeResult is not None: 93 | report.write_line('
') 94 | report.write_line('

启动时间测试结果:
%s

'%formatStr2(startTimeResult)) 95 | report.write_line('
') 96 | #资源图表 97 | print os.path.join(report_dir,"Test_cpuInfo.png") 98 | if os.path.exists(os.path.join(report_dir,"Test_cpuInfo.png")): 99 | 100 | report.write_line('
') 101 | report.write_line('

CPU使用统计(%):

') 102 | report.write_line('

本次测试CPU的平均值(取出最大值和最小值)为(%):'+str(avgCpuAndMem[0])+'

') 103 | report.write_line('') 104 | report.write_line('
') 105 | 106 | if os.path.exists(os.path.join(report_dir,"Test_MemoryInfo.png")): 107 | report.write_line('
') 108 | report.write_line('

内存使用统计(MB/s):

') 109 | report.write_line('

本次测试内存的平均值(取出最大值和最小值)为(MB/s):'+str(avgCpuAndMem[1])+'

') 110 | report.write_line('') 111 | report.write_line('
') 112 | 113 | if os.path.exists(os.path.join(report_dir,"Test_networkTraffic.png")): 114 | report.write_line('
') 115 | report.write_line('

流量使用统计(KB/s):

') 116 | report.write_line('

本次测试的总流量为(KB):'+str(round((networkTraffic.total_bytes/1024.0),2))+'KB

') 117 | networkTraffic.total_bytes = 0 118 | report.write_line('') 119 | report.write_line('
') 120 | 121 | if os.path.exists(os.path.join(report_dir,"Test_powerInfo.png")): 122 | report.write_line('
') 123 | report.write_line('

电量使用统计(%):

') 124 | report.write_line('') 125 | report.write_line('
') 126 | #测试结果详细部分--end 127 | 128 | report.write_closing_html() 129 | print "报告生成完毕。".decode("utf-8") 130 | return report.fn 131 | 132 | def getReportConent(fileName=None): 133 | if fileName is not None: 134 | reportFile = os.path.join(report_dir,fileName) 135 | return open(reportFile).read() 136 | return None 137 | 138 | 139 | if __name__ == "__main__": 140 | print getAvgCpuAndMemory("C:\\Users\\zhaowei\\workspace\\MobilePerformance\\logs\\task_0906144920") 141 | 142 | -------------------------------------------------------------------------------- /Report/generateReport.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/Report/generateReport.pyc -------------------------------------------------------------------------------- /Report/reportWritor.py: -------------------------------------------------------------------------------- 1 | # -* - coding: UTF-8 -* - 2 | 3 | import os,sys 4 | import time 5 | 6 | 7 | class Report(object): 8 | 9 | 10 | def __init__(self, results_dir): 11 | self.results_dir = results_dir 12 | timeStr = time.strftime("%Y%m%d%H%M%S", time.localtime()) 13 | self.fn = os.path.join(results_dir,'result_%s.html'%timeStr) 14 | if not os.path.exists(self.fn): 15 | f = open(self.fn,'w') 16 | f.close() 17 | self.write_head_html() 18 | 19 | def write_line(self, line): 20 | with open(self.fn, 'a') as f: 21 | f.write('%s\n' % line) 22 | 23 | 24 | def write_head_html(self): 25 | with open(self.fn, 'w') as f: 26 | f.write("""\ 27 | 29 | 30 | 31 | App性能测试报告(Android) 32 | 33 | 34 | 83 | 84 | 85 | """) 86 | 87 | 88 | def write_closing_html(self): 89 | with open(self.fn, 'a') as f: 90 | f.write("""\ 91 | 92 | 93 | """) 94 | -------------------------------------------------------------------------------- /Report/reportWritor.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/Report/reportWritor.pyc -------------------------------------------------------------------------------- /ResMonitor/MemoryCPUMonitor.py: -------------------------------------------------------------------------------- 1 | #-*- coding: UTF-8 -*- 2 | 3 | import threading 4 | import os 5 | import time 6 | import subprocess 7 | import sys 8 | import signal 9 | import re 10 | from Common import const 11 | from Common.userConf import UserConf 12 | 13 | class memoryCPUMonitor(threading.Thread): 14 | over = False 15 | 16 | def __init__(self,logFolder,packageName,caseID=None,deviceID=None): 17 | threading.Thread.__init__(self) 18 | self.over = False 19 | self.package = packageName 20 | self.logFolder = logFolder 21 | 22 | if caseID is None: 23 | self.picPre = "Test" 24 | self.logFile = os.path.join(self.logFolder,"memory.log") 25 | else: 26 | self.picPre = caseID 27 | self.logFile = os.path.join(self.logFolder,"%s_memory.log"%caseID) 28 | if deviceID is None: 29 | self.cmdStr = 'adb shell "top -d 1 -s cpu | grep %s$" > "%s"'%(self.package,self.logFile )#间隔1秒获取一次 30 | else: 31 | self.cmdStr = 'adb -s %s shell "top -d 1 -s cpu | grep %s$" > "%s"'%(deviceID,self.package,self.logFile) 32 | 33 | self.over = False 34 | 35 | @staticmethod 36 | def terminate(): 37 | memoryCPUMonitor.over = True 38 | 39 | 40 | def run(self): 41 | "开始执行" 42 | print "CPU/Memory监控启动...".decode("utf-8") 43 | print self.cmdStr 44 | sub_process = subprocess.Popen(self.cmdStr,shell=True) 45 | memoryCPUMonitor.over = False 46 | while not memoryCPUMonitor.over: 47 | time.sleep(1) 48 | 49 | else: 50 | time.sleep(10) 51 | print "数据收集结束。".decode("utf-8") 52 | os.system("taskkill /F /IM adb.exe") 53 | time.sleep(2) 54 | 55 | #处理文件路径中带空格的情况 56 | if " " in const.jarFile: 57 | cmdStr = 'java -jar "'+const.jarFile+'" "'+self.logFile+'" '+self.picPre+' "'+self.logFolder+'" 0 '+UserConf.packageName 58 | else: 59 | cmdStr = 'java -jar '+const.jarFile+' '+self.logFile+' '+self.picPre+' '+self.logFolder+' 0 '+UserConf.packageName 60 | if sys.platform.startswith("win"): 61 | subprocess.call(cmdStr) 62 | elif sys.platform.startswith('linux'): 63 | subprocess.call(cmdStr,shell=True) 64 | print "制图完毕。".decode("utf-8") 65 | 66 | 67 | 68 | if __name__ == "__main__": 69 | 70 | print "over" -------------------------------------------------------------------------------- /ResMonitor/MemoryCPUMonitor.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/ResMonitor/MemoryCPUMonitor.pyc -------------------------------------------------------------------------------- /ResMonitor/NetworkTraffic.py: -------------------------------------------------------------------------------- 1 | #-*- coding: UTF-8 -*- 2 | ''' 3 | Created on 2016-2-25 4 | 5 | @author: zhaowei 6 | ''' 7 | import os 8 | import platform 9 | import threading 10 | import time 11 | import sys 12 | import subprocess 13 | from Common import const 14 | from Common.userConf import UserConf 15 | 16 | 17 | class networkTraffic(threading.Thread): 18 | thread_stop = False 19 | total_bytes = 0 20 | def __init__(self,logFolder,deviceID,interval=1): 21 | threading.Thread.__init__(self) 22 | self.deviceNo = deviceID 23 | self.picPre = "Test" 24 | self.logFolder = logFolder 25 | self.pid = self.__getPid() 26 | self.uid = self.getAppUID() 27 | self.interval = interval 28 | bytesByUID = self.getBytesByUID() 29 | self.start_receive_bytes = bytesByUID[0] 30 | self.start_send_bytes = bytesByUID[1] 31 | # self.thread_stop = False 32 | self.logFile = logFolder+"/network.log" 33 | if os.path.exists(self.logFile): 34 | os.remove(self.logFile) 35 | self.networkLog = open(self.logFile,"a") 36 | self.networkLog.write("receiveBytes\tsendBytes\n") 37 | 38 | def run(self): 39 | print "流量监控启动...".decode("utf-8") 40 | networkTraffic.thread_stop = False 41 | time.sleep(3) 42 | while not networkTraffic.thread_stop: 43 | time.sleep(self.interval) 44 | bytesByUID = self.getBytesByUID() 45 | end_receive_bytes = bytesByUID[0] 46 | end_send_bytes = bytesByUID[1] 47 | receive_bytes = end_receive_bytes - self.start_receive_bytes 48 | send_bytes = end_send_bytes - self.start_send_bytes 49 | networkTraffic.total_bytes+= (receive_bytes+send_bytes) 50 | self.networkLog.write(str(receive_bytes)+"\t"+str(send_bytes)+"\n") 51 | self.start_receive_bytes = end_receive_bytes 52 | self.start_send_bytes = end_send_bytes 53 | else: 54 | self.networkLog.flush() 55 | self.networkLog.close() 56 | 57 | time.sleep(2) 58 | #处理文件路径中带空格的情况 59 | if " " in const.jarFile: 60 | cmdStr = 'java -jar "'+const.jarFile+'" "'+self.logFile+'" '+self.picPre+' "'+self.logFolder+'" 1 '+UserConf.packageName 61 | else: 62 | cmdStr = 'java -jar '+const.jarFile+' '+self.logFile+' '+self.picPre+' '+self.logFolder+' 1 '+UserConf.packageName 63 | if sys.platform.startswith("win"): 64 | subprocess.call(cmdStr) 65 | elif sys.platform.startswith('linux'): 66 | subprocess.call(cmdStr,shell=True) 67 | print "制图完毕。".decode("utf-8") 68 | 69 | @staticmethod 70 | def terminate(): 71 | networkTraffic.thread_stop = True 72 | 73 | def isWindowsSystem(self): 74 | return 'windows' in platform.system().lower() 75 | 76 | 77 | def __scanDevices(self): 78 | targets = [] 79 | if self.isWindowsSystem(): 80 | result = os.popen("adb devices").read() 81 | devices = result.split("\n")[1:] 82 | 83 | for device in devices: 84 | if device.strip(): 85 | tmp = device.split() 86 | if len(tmp)==2 and tmp[1]=='device': 87 | targets.append(tmp[0]) 88 | 89 | return targets 90 | 91 | def getDeviceNo(self): 92 | devices = self.__scanDevices() 93 | if(len(devices)==0): 94 | raise Exception("手机没有连接,请连接手机") 95 | return devices[0] 96 | def getAppUID(self): 97 | "得到APP的UID" 98 | cmdStr = 'adb -s %s shell "cat /proc/%s/status | grep Uid"' % (self.deviceNo,self.pid) 99 | uid = os.popen(cmdStr).read().split()[1] 100 | return uid 101 | 102 | def __getPid(self): 103 | "获取的PID,APP必须已经启动" 104 | try: 105 | cmdStr = 'adb -s %s shell "ps | grep %s$"' % (self.deviceNo,UserConf.packageName) 106 | pidStr = os.popen(cmdStr).read() 107 | pid = pidStr.split()[1] 108 | return pid 109 | except Exception as e: 110 | print "APP没有启动,启动APP...".decode("utf-8") 111 | self.app_start(UserConf.packageName,UserConf.activityName) 112 | time.sleep(5) 113 | return self.__getPid() 114 | 115 | 116 | def __getAppUIDByPackage(self): 117 | app_uid = os.popen('adb -s %s shell su -c "cat /data/system/packages.list | grep %s"' % (self.deviceNo,UserConf.packageName)).read().split()[1] 118 | return app_uid 119 | 120 | def getReceiveBytes(self): 121 | "获取APP的接收的总字节数,手机重启后该数据会被清零,建议及时保存数据" 122 | cmdStr = "adb -s %s shell cat /proc/uid_stat/%s/tcp_rcv" % (self.deviceNo,self.uid) 123 | receiveBytes = os.popen(cmdStr).read().split("\n")[0] 124 | return long(receiveBytes) 125 | 126 | 127 | def getReceiveBytesByPid(self): 128 | "获取APP的接收的总字节数,手机重启后该数据会被清零,建议及时保存数据" 129 | self.pid = self.__getPid() 130 | cmdStr = 'adb -s %s shell "cat /proc/%s/net/dev |grep wlan0"' % (self.deviceNo,self.pid) 131 | receiveBytes = os.popen(cmdStr).read().split()[1] 132 | return long(receiveBytes) 133 | 134 | def getSendBytesByPid(self): 135 | "获取APP发送的总字节数,手机重启后该数据会被清零,建议及时保存数据" 136 | self.pid = self.__getPid() 137 | cmdStr = 'adb -s %s shell "cat /proc/%s/net/dev |grep wlan0"' % (self.deviceNo,self.pid) 138 | sendBytes = os.popen(cmdStr).read().split()[9] 139 | return long(sendBytes) 140 | 141 | def getBytesByUID(self): 142 | "获取APP的接收的总字节数,手机重启后该数据会被清零,建议及时保存数据" 143 | cmdStr = 'adb -s %s shell "cat /proc/net/xt_qtaguid/stats | grep %s | grep wlan0"' % (self.deviceNo,self.uid) 144 | rec_rows = os.popen(cmdStr).read().replace("\r","").split("\n") 145 | receiveBytes = 0 146 | sendBytes = 0 147 | for i in range(0,len(rec_rows)-1): 148 | row = rec_rows[i] 149 | receiveBytes+=long(row.split()[5]) 150 | sendBytes+=long(row.split()[7]) 151 | return [receiveBytes,sendBytes] 152 | 153 | def getSendBytes(self): 154 | "获取APP发送的总字节数,手机重启后该数据会被清零,建议及时保存数据" 155 | cmdStr = "adb -s %s shell cat /proc/uid_stat/%s/tcp_snd" % (self.deviceNo,self.uid) 156 | sendBytes = os.popen(cmdStr).read().split("\n")[0] 157 | return long(sendBytes) 158 | 159 | def app_start(self,packageName=UserConf.packageName,activityName=UserConf.activityName): 160 | "启动APP" 161 | cmdStr = "adb shell am start -n %s/%s"%(packageName,activityName) 162 | os.system(cmdStr) 163 | 164 | if __name__ == "__main__": 165 | t = networkTraffic(r"C:\Users\zhaowei\Desktop\temp","9bae9a99") 166 | t.getBytesByUID() 167 | -------------------------------------------------------------------------------- /ResMonitor/NetworkTraffic.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/ResMonitor/NetworkTraffic.pyc -------------------------------------------------------------------------------- /ResMonitor/PowerMonitor.py: -------------------------------------------------------------------------------- 1 | #-*- coding: UTF-8 -*- 2 | 3 | import threading 4 | import os 5 | from Common.userConf import UserConf 6 | 7 | class powerMonitor(threading.Thread): 8 | over = False 9 | 10 | def __init__(self,logFolder,deviceNo=None,packageName=UserConf.packageName): 11 | threading.Thread.__init__(self) 12 | self.packageName = packageName 13 | self.deviceNo = deviceNo 14 | self.over = False 15 | 16 | @staticmethod 17 | def terminate(): 18 | powerMonitor.over = True 19 | 20 | def getCurrentBattery(self): 21 | "获取当前手机的电量" 22 | if self.deviceNo: 23 | cmdStr = 'adb -s %s shell "dumpsys battery | grep level"' % (self.deviceNo) 24 | else: 25 | cmdStr = 'adb shell "dumpsys battery | grep level"' 26 | 27 | current_battery = os.popen(cmdStr).read().split(": ")[1] 28 | return current_battery 29 | def run(self): 30 | "执行监控" 31 | print "电量监控启动...".decode("utf-8") 32 | while not powerMonitor.over: 33 | print "AAA" 34 | 35 | if __name__ == "__main__": 36 | p = powerMonitor("353BCJMKJEF3") 37 | print p.getCurrentBattery() -------------------------------------------------------------------------------- /ResMonitor/PowerMonitor.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/ResMonitor/PowerMonitor.pyc -------------------------------------------------------------------------------- /ResMonitor/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/ResMonitor/__init__.py -------------------------------------------------------------------------------- /ResMonitor/__init__.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/ResMonitor/__init__.pyc -------------------------------------------------------------------------------- /StartTime/StartTime.py: -------------------------------------------------------------------------------- 1 | #-*- coding: UTF-8 -*- 2 | ''' 3 | Created on 2016-2-26 4 | 5 | @author: zhaowei 6 | ''' 7 | import os 8 | from threading import Thread 9 | import time 10 | from Common.userConf import UserConf 11 | 12 | 13 | class startTime(object): 14 | def __init__(self,times,packageName=UserConf.packageName,activityName=UserConf.activityName): 15 | self.packageName = packageName 16 | self.activityName = activityName 17 | self.times = times 18 | 19 | def getStartTime(self): 20 | "获取App一次启动的时间(应用关闭已经关闭,不在后台)单位:毫秒" 21 | self.stopAPP() 22 | cmd = 'adb shell "am start -W -n %s/%s | grep TotalTime"' % (self.packageName,self.activityName) 23 | time = os.popen(cmd).read().split(": ")[1] 24 | return long(time) 25 | 26 | def stopAPP(self): 27 | stopCmd = "adb shell am force-stop %s" % self.packageName 28 | os.system(stopCmd) 29 | 30 | def execute(self): 31 | "根据给定的次数进行启动APP,获取APP的启动时间,以字典的形式返回,key分别为:max:最大时间,min最小时间,avg:平均时间,count:次数 ,单位:毫秒,默认次数为5次" 32 | r = [] 33 | appStartTime = {} 34 | 35 | for i in xrange(self.times): 36 | startTime = self.getStartTime() 37 | r.append(startTime) 38 | print ("第"+str(i+1)+"次的启动时间为:"+str(startTime)).decode("utf-8") 39 | time.sleep(1) 40 | 41 | appStartTime['max'] = max(r) 42 | appStartTime['min'] = min(r) 43 | appStartTime['avg'] = sum(r)/self.times 44 | if len(appStartTime)>2: 45 | r.sort() 46 | appStartTimeNotMaxAndNotMin = r[1:-1] 47 | appStartTime['avg'] = sum(appStartTimeNotMaxAndNotMin)/(self.times-2) 48 | appStartTime['count'] = self.times 49 | print appStartTime 50 | return appStartTime 51 | 52 | 53 | 54 | if __name__ == "__main__": 55 | s = startTime(9) 56 | result = s.execute() 57 | print result -------------------------------------------------------------------------------- /StartTime/StartTime.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/StartTime/StartTime.pyc -------------------------------------------------------------------------------- /StartTime/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/StartTime/__init__.py -------------------------------------------------------------------------------- /StartTime/__init__.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/StartTime/__init__.pyc -------------------------------------------------------------------------------- /logs/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/logs/.DS_Store -------------------------------------------------------------------------------- /res/logo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/res/logo.ico -------------------------------------------------------------------------------- /run.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | python MainWindow.py 3 | pause --------------------------------------------------------------------------------