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)