我的tkinter学习笔记4

2020-04-15 18:31:29 浏览数 (1)

继续完善上篇的小工具功能,增加以下功能

a、增加关于作者信息标签

b、增加跑Monkey功能

c、增加日志输出和文件保存路径选择

一、先看下效果

二、实例代码

代码语言:javascript复制
# coding:utf-8
from tkinter import *
from datetime import datetime
from tkinter import messagebox
import time,os
import threading
import tkinter as tk
from tkinter import filedialog, dialog

class MonkeyTest:
    def __init__(self):
        self.root = Tk()
        self.root.title('APP测试小工具 V1.0')
        self.line = 1  # 用于统计monkey日志的行数
        self.flagWhile = 1  # 循环判断标志位

    def getPacky(self):
        #  adb shell dumpsys window w |findstr / |findstr name=
        zhi = (os.popen('adb shell dumpsys window w |findstr / |findstr name=').read())
        d = (zhi.strip().split('n'))
        pack = d[0].split('=')[-1]
        # print(pack)
        result = pack.split('/')[0]
        # print(result)
        self.entryPkg.delete(0, END)  # 清空设备id编辑框
        self.entryPkg.insert(7, result)  # 填写包名

    def get_Activity(self):
        zhi = (os.popen('adb shell dumpsys window w |findstr / |findstr name=').read())
        d = (zhi.strip().split('n'))
        act = d[0].split('=')[-1]
        print(act)
        activity = act.split('/')[1]
        print(activity)
        result = activity.replace(')', '')
        # print(result)
        self.entryAct.delete(0, END)  # 清空编辑框
        self.entryAct.insert(8, result)  # 填写Act

    def createRun(self):
        """开始运行"""
        # self.frame = Frame()
        self.frame = tk.LabelFrame(self.root, text="Monkey测试", font=('微软雅黑', 20))
        self.frame.pack()
        self.create_menu()
        rowIsANR, rowPackage, rowAct, rowRemind, rowExecute, rowInfo = 6, 7, 8, 9, 10, 11
        padxLabel, padyLabel = 5, 10
        padxEntry, padyEntry = 20, 20
        padxButton, padyButton = 10, 20
        padxListbox, padyListbox = 10, 10

        # 设备ID
        btnDevice = Button(self.frame, text='获取设备ID', command=self.getDeivceID)
        btnDevice.grid(row=0, column=0, sticky=E, padx=padxLabel, pady=padyLabel)
        self.entryDevice = Entry(self.frame)
        self.entryDevice.grid(row=0, column=1, sticky=W, padx=padxEntry)
        # 包名
        btnPkg = Button(self.frame, text='获取包名', command=self.getPacky)
        btnPkg.grid(row=1, column=0, sticky=E, padx=padxLabel, pady=padyLabel)
        self.entryPkg = Entry(self.frame)
        self.entryPkg.grid(row=1, column=1, sticky=W, padx=padxEntry)
        # Activity
        btnAct = Button(self.frame, text='获取Activity', command=self.get_Activity)
        btnAct.grid(row=2, column=0, sticky=E, padx=padxLabel, pady=padyLabel)
        self.entryAct = Entry(self.frame)
        self.entryAct.grid(row=2, column=1, sticky=W, padx=padxEntry)
        # crash
        labelCrash = Label(self.frame, text='出现crash是否继续:')
        labelCrash.grid(row=3, column=0, sticky=E, padx=padxLabel, pady=padyLabel)
        self.vCrash = IntVar()
        btnCrash = Checkbutton(self.frame, variable=self.vCrash)
        btnCrash.select()  # 默认勾选
        btnCrash.grid(row=3, column=1, sticky=W, padx=padxButton)
        # ANR
        labelANR = Label(self.frame, text='出现ANR是否继续:')
        labelANR.grid(row=3, column=2, sticky=E, padx=padxLabel, pady=padyLabel)
        self.vANR = IntVar()
        btnANR = Checkbutton(self.frame, variable=self.vANR)
        btnANR.select()  # 默认勾选
        btnANR.grid(row=3, column=3, sticky=W, padx=padxButton)
        # 事件次数
        labelEvent = Label(self.frame, text='事件次数:')
        labelEvent.grid(row=0, column=2, sticky=W, padx=padxLabel, pady=padyLabel)
        self.entryEvent = Entry(self.frame)
        self.entryEvent.grid(row=0, column=3, sticky=E, padx=padxEntry)
        # seed值
        labelSeed = Label(self.frame, text='seed值:')
        labelSeed.grid(row=1, column=2, sticky=W, padx=padxLabel, pady=padyLabel)
        self.entrySeed = Entry(self.frame)
        self.entrySeed.grid(row=1, column=3, sticky=E, padx=padxEntry)

        # 提示信息
        self.labelRemind = Label(self.frame, fg='red', font=('微软雅黑'))
        self.labelRemind.grid(row=rowRemind, column=0, columnspan=2, sticky=E   W, padx=padxLabel, pady=padyLabel)
        # 执行
        self.btnExecute = Button(self.frame, text='  执行  ', command=self.execute)
        self.btnExecute.grid(row=rowExecute, column=0, sticky=E, padx=padxButton)
        # 停止
        btnStop = Button(self.frame, text='  停止  ', command=self.stop)
        btnStop.grid(row=rowExecute, column=1, sticky=W, padx=padxButton)
        # 展示信息
        self.listInfo = Listbox(self.frame, width=70, height=10)
        self.listInfo.grid(row=rowInfo, column=0, columnspan=2, padx=padxListbox, pady=padyListbox)
        self.root.mainloop()

    def getDeivceID(self):
        '''
        获取设备id
        :return:
        '''
        cmd = 'adb devices >c:/devices.log'
        os.system(cmd)
        with open('c:/devices.log','r') as f:
            result = f.readlines()[1].split('t')[0]
        self.entryDevice.delete(0, END) # 清空设备id编辑框
        self.entryDevice.insert(0, result)  # 填写设备id

    def execute(self):
        # 设备id不为空,运行脚本时其实没有限定设备id,此项主要用来检测是否能运行adb
        if len(self.entryDevice.get().strip()) == 0:
            self.labelRemind['text'] = '请输入设备ID'
            return
        # 事件次数为数字
        self.event = self.entryEvent.get().strip()
        if not self.event.isdigit():
            self.labelRemind['text'] = '请输入正确的次数'
            return
        # seed值为数字
        self.seed = self.entrySeed.get().strip()
        if not self.seed.isdigit():
            self.labelRemind['text'] = '请输入正确的seed'
            return
        # 是否忽略crash
        self.crash = '--ignore-crashes'
        if self.vCrash.get() == 0:
            self.crash = ''
        # 是否忽略ANR
        self.anr = '--ignore-timeouts'
        if self.vANR.get() == 0:
            self.anr = ''
        # 包名不为空
        self.pkg = self.entryPkg.get().strip()
        if len(self.pkg) == 0:
            self.labelRemind['text'] = '需要填写测试的包名'
            return
        # 按钮置灰
        self.btnExecute['state'] = 'disabled'
        lTime = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        self.listInfo.insert(END, lTime   '  Monkey测试开始。。。')
        # 重置提示语
        self.labelRemind['text'] = ''
        # 重置行数
        self.line = 1
        # 重置循环标志位
        self.flagWhile = 1
        # 运行monkey语句
        t1 = threading.Thread(target=self.executeCmd)
        t1.start()
        # 显示monkey日志
        t2 = threading.Thread(target=self.startReadLog)
        t2.start()

    def executeCmd(self):
        cmd = 'adb shell monkey -p '   self.pkg   ' '   self.crash   ' '   self.anr   ' --monitor-native-crashes --throttle 1000 -s '   self.seed   ' -v -v -v '   self.event   ' >c:/monkey.log'
        os.system(cmd)

    def startReadLog(self):
        '''
        5秒读一次monkey的log,
        第一次等5秒是让adb命令先运行,防止先读log而又没有monkey.log文件,导致异常
        :return:
        '''
        while self.flagWhile > 0:   # 标志位初始值大于0,进入循环
            time.sleep(5)
            self.readLog()

    def stop(self):
        self.btnExecute['state'] = 'active' # 激活执行按钮
        self.flagWhile = -1 # 标志位小于0,跳出循环

    def readLog(self):
        count = 1
        f = open('c:/monkey.log', 'r', encoding='utf8')
        for i in f.readlines():
            count = count   1   # 记录每次读取log的行数,每读一行,计数 1
            # count > line 防止重复insret
            if count > self.line and ('// CRASH:' in i or 'ANR in ' in i):
                lTime = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                self.listInfo.insert(END, lTime   '  '   i)
            # 存在'// Monkey finished',就判断monkey结束
            elif '// Monkey finished' in i:
                lTime = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                self.listInfo.insert(END, lTime   '  Monkey测试结束!')
                self.stop()
        # print(self.line, count)
        self.line = count

    def create_menu(self):
        # 创建一个下拉菜单“文件”,然后将它添加到顶级菜单中
        MenuBar = tk.Menu(self.root)
        # 将菜单栏放到主窗口
        self.root.config(menu=MenuBar)
        # 创建文件菜单,不显示分窗
        fileBar = tk.Menu(MenuBar, tearoff=0)
        # 添加文件菜单项
        fileBar.add_command(label="Open File", command=self.open_file)
        fileBar.add_command(label="Save File", command=self.save_file)
        # 创建分割线
        fileBar.add_separator()
        fileBar.add_command(label="exit", command=self.root.quit)
        # 将文件菜单添加到菜单栏
        MenuBar.add_cascade(label="File", menu=fileBar)
        helpmenu = Menu(MenuBar, tearoff=0)
        helpmenu.add_command(label="About", command=self.getAbout)
        MenuBar.add_cascade(label="Help", menu=helpmenu)

    def open_file(self):
        '''
        打开文件
        :return:
        '''
        global file_path
        global file_text
        file_path = filedialog.askopenfilename(title=u'选择文件', initialdir=(os.path.expanduser('H:/')))
        print('打开文件:', file_path)
        if file_path is not None:
            with open(file=file_path, mode='r ', encoding='utf-8') as file:
                file_text = file.read()
            self.listInfo.insert('insert', file_text)

    def save_file(self):
        global file_path
        global file_text
        file_path = filedialog.asksaveasfilename(title=u'保存文件')
        print('保存文件:', file_path)
        # file_text = text1.get('1.0', tk.END)
        if file_path is not None:
            with open(file=file_path, mode='a ', encoding='utf-8') as file:
                file.write(file_text)
            # text1.delete('1.0', tk.END)
            dialog.Dialog(None, {'title': '是否关闭弹框', 'text': '保存完成', 'bitmap': 'warning', 'default': 0,
                                 'strings': ('确定', '取消')})
            print('保存完成')


    def getAbout(self):
        messagebox.showinfo(title='about Author', message=u'工具使用说明:n 1:快速获取设备ID、应用包名和Activity;n '
                             u'2:执行Monkey测试,可设定日志保存路径;n 3:欢迎关注公众号【自学测试之道】')

m = MonkeyTest()
m.createRun()

后续可以根据自己的工作情况,逐步完善测试工具,当然,学习还是要持续进行的

0 人点赞