from PIL import ImageGrab import os, time, random, sys import win32api, win32con, win32com.client, win32gui from ctypes import * class MonkeyTest: # 定义随机输入字符,此处定义0x30~0x39为数字0~9,0x41~0x5A对应a~z VK_CODE = [0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A] def __init__(self, title): self.hwnd = None # 定义当前启动的应用程序的窗口句柄 self.title = title # 定义一个期望的窗口标题关键字 pas # 参数count用于定义执行总次数 def start_monkey(self, count): for i in range(count): # 根据执行总次数来进行随机操作 rand_num = random.randint(0, count) % 26 if rand_num < 5: self.bring_top() self.random_input() elif rand_num < 10: self.bring_top() self.random_dblclick() elif rand_num < 15: self.bring_top() self.check_window() elif rand_num < 20: self.bring_top() self.screen_shot() else: self.bring_top() self.random_click() # 开启一个应用程序,如需要启动一个Web应用程序,可以使用如下命令: # iexplore.exe "http://www.woniuxy.com/" def start_app(self, cmd): # start /b 命令的目的是让程序在后台运行,不阻塞当前程序的运行主线程 os.system("start /b " + cmd) time.sleep(3) # 获取当前启动的应用程序窗口对象并将其最大化和置顶 self.hwnd = win32gui.GetForegroundWindow() self.bring_top() # win32gui.ShowWindow(self.hwnd, win32con.SW_MAXIMIZE) # 最大化 print("应用程序[" + cmd + "]已经正常启动.") # 日志输出 # 模拟随机单击 def random_click(self): self.random_move() win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0) win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0) print("在当前位置进行单击操作.") # 日志输出 # 模拟随机双击 def random_dblclick(self): self.random_move() win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0) win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0) win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0) win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0) print("在当前位置进行双击操作.") # 日志输出 # 模拟随机输入 def random_input(self): self.random_move() # 定义输入数字的个数 for i in range(random.randint(3,10)): index = random.randint(0, len(self.VK_CODE)-1) win32api.keybd_event(self.VK_CODE[index], 0, 0, 0) win32api.keybd_event(self.VK_CODE[index], 0, win32con.KEYEVENTF_KEYUP, 0) time.sleep(0.2) print("在当前位置输入一个字符串.") # 日志输出 # 模拟随机移动 def random_move(self): # 获取到当前屏幕的分辨率(进而用于限定在对应的应用程序区域进行操作) # right和bottom对应的值即为分辨率的宽和高 # 也可以根据应用程序界面直接获取到应用程序的坐标 (left, top, right, bottom) = win32gui.GetWindowRect(self.hwnd) # 为稳妥考虑,保证所有操作一定是在窗口内进行,建议适当减少数量 (left, top, right, bottom) = (left + 10, top + 10, right - 10, bottom - 10) # 输出当前容器的位置情况 print("当前窗口的位置为:(%d, %d, %d, %d)" %(left, top, right, bottom)) # 基于right和bottom的大小生成一个当前窗口内的随机坐标 random_x = random.randint(0, right) random_y = random.randint(0, bottom) windll.user32.SetCursorPos(random_x, random_y) print("将鼠标移动到位置:%d:%d"%(random_x,random_y)) # 日志输出
# 将目标窗口置顶 def bring_top(self): win32com.client.Dispatch("WScript.Shell").SendKeys('%') win32gui.SetForegroundWindow(self.hwnd) win32gui.BringWindowToTop(self.hwnd) print("将本运行程序窗口置顶.") # 日志输出 # 运行过程中进行截图操作并保存到指定目录下 def screen_shot(self): # 利用年月日_时分秒的格式命名截图文件,便于后续按顺序查看测试现场的情况 image_name = time.strftime('%Y%m%d_%H%M%S',time.localtime()) + ".png" im = ImageGrab.grab() im.save("D:/ScreenShot/" + image_name) print("对当前屏幕进行截图,并保存为:" + image_name) # 日志输出 # 每进行一次操作之前,均判断一下是否有 def check_window(self): hwnd = win32gui.GetForegroundWindow() title = win32gui.GetWindowText(hwnd) if self.title not in title: print("窗口不在最顶端,测试程序将中止运行.") # 日志输出 sys.exit(0)
# 对Windows自带计算器进行Monkey测试 mt = MonkeyTest("计算器") mt.start_app("calc.exe") mt.start_monkey(10) |