使用python进行windows自动化测试

最近开始学习整理python在windows自动化测试中的使用,觉得挺有意思的

主要思路,在windows下,主要通过启进程,然后查找进程的句柄,然后再操作这个句柄,包括点击,填写文字,关闭,获取文字等操作

下面以一个简单的校验文件md5值的操作来介绍一个python的应用,当然python中有校验md5的函数,不用非要使用工具来校验,这里只是练习使用python来自动化操作

所用的工具有SpyLite,用于查看窗口ID,句柄等信息

工具下载

http://www.xiazaiba.com/html/358.html

http://www.xiazaiba.com/html/5861.html

我们要达到的目的是通过md5校验工具将文件的md5值保存到一个log文档中

测试的目录结构

--automd5--

--needCheck--

checkmd5.py

SpyLite24.exe

Hash.exe

needCheck目录放需要检查md5的文件

001#! /usr/bin/env python
002#coding=gbk
003 
004import time,re,ctypes
005import os,sys,subprocess,win32gui,win32con,win32api
006import glob,time
007 
008#启进程函数
009def createProcess(cmd, wait = False):
010if wait:
011proc = tryExcept(subprocess.Popen, cmd, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
012else:
013proc = tryExcept(subprocess.Popen, cmd)
014if isExcept(proc):
015return
016if not wait:
017return proc.pid
018proc.communicate()
019 
020 
021def tryExcept(func, *params, **paramMap):
022try:
023return func(*params, **paramMap)
024except Exception, e:
025return e
026def isExcept(e, eType = Exception):
027return isinstance(e, eType)
028 
029 
030class BaseWindow:
031@staticmethod
032def parseClickConfig(clkCfg):
033if clkCfg == None:
034return None, None, False, 0
035if type(clkCfg) == bool:
036return None, None, clkCfg, 0
037if type(clkCfg) == int:
038return None, None, False, clkCfg
039if len(clkCfg) == 2:
040if type(clkCfg[0]) == int and type(clkCfg[1]) == int:
041return clkCfg[0], clkCfg[1], False, 0
042return None, None, clkCfg[0], clkCfg[1]
043if len(clkCfg) == 3:
044if type(clkCfg[2]) == bool:
045return clkCfg[0], clkCfg[1], clkCfg[2], 0
046return clkCfg[0], clkCfg[1], False, clkCfg[2]
047return clkCfg
048 
049 
050#点击窗口
051#clkCfg:byDrv|mode|(x,y)|(byDrv,mode)|(x,y,byDrv)|(x,y,mode)|(x,y,byDrv,mode)
052def clickWindow(hwnd, clkCfg = None):
053if isRawWindow(hwnd):
054return
055topWindow(hwnd)
056rect = getWindowRect(hwnd)
057if not rect:
058return
059x, y, byDrv, mode = BaseWindow.parseClickConfig(clkCfg)
060if x == None:
061x = (rect[0] + rect[2]) / 2
062elif x < 0:
063x += rect[2]
064else:
065x += rect[0]
066if y == None:
067y = (rect[1] + rect[3]) / 2
068elif y < 0:
069y += rect[3]
070else:
071y += rect[1]
072clickMouse(x, y, byDrv, mode)
073 
074#点击鼠标
075CLICK_MOUSE = 0
076CLICK_MOUSE_DOUBLE = 1
077CLICK_MOUSE_RIGHT = 2
078 
079def clickMouse(x, y, byDrv = False, mode = CLICK_MOUSE):
080moveMouse(x, y, byDrv)
081downMsg, upMsg = win32con.MOUSEEVENTF_LEFTDOWN, win32con.MOUSEEVENTF_LEFTUP
082if mode == CLICK_MOUSE_RIGHT:
083downMsg, upMsg = win32con.MOUSEEVENTF_RIGHTDOWN, win32con.MOUSEEVENTF_RIGHTUP
084win32api.mouse_event(downMsg, 0, 0, 0, 0)
085win32api.mouse_event(upMsg, 0, 0, 0, 0)
086if mode == CLICK_MOUSE_DOUBLE:
087win32api.mouse_event(downMsg, 0, 0, 0, 0)
088win32api.mouse_event(upMsg, 0, 0, 0, 0)
089 
090#移动鼠标
091def moveMouse(x, y, byDrv = False):
092w, h = win32api.GetSystemMetrics(0), win32api.GetSystemMetrics(1)
093x, y = int(float(x) / w * 65535), int(float(y) / h * 65535)
094win32api.mouse_event(win32con.MOUSEEVENTF_MOVE | win32con.MOUSEEVENTF_ABSOLUTE, x, y, 0, 0)
095 
096 
097#获得窗口尺寸
098def getWindowRect(hwnd):
099rect = tryExcept(win32gui.GetWindowRect, hwnd)
100if not isExcept(rect):
101return rect
102 
103#置顶窗口
104def topWindow(hwnd):
105fgHwnd = win32gui.GetForegroundWindow()
106if fgHwnd == hwnd:
107return True
108rst = tryExcept(win32gui.SetForegroundWindow, hwnd)
109if not isExcept(rst):
110return True
111return getWindowClass(fgHwnd) == 'Progman' and getWindowText(fgHwnd) == 'Program Manager'
112 
113 
114##获取窗口文字
115def getWindowText(hwnd, buf = ctypes.c_buffer(1024)):
116size = ctypes.sizeof(buf)
117ctypes.memset(buf, 0, size)
118tryExcept(win32gui.SendMessageTimeout, hwnd, win32con.WM_GETTEXT, size, buf, win32con.SMTO_ABORTIFHUNG, 10)
119return buf.value.strip()
120 
121#获取窗口类名
122def getWindowClass(hwnd, buf = ctypes.c_buffer(1024)):
123size = ctypes.sizeof(buf)
124ctypes.memset(buf, 0, size)
125ctypes.windll.user32.GetClassNameA(hwnd, ctypes.addressof(buf), size)
126return buf.value.strip()
127 
128#查找第一个窗口
129#title:text,class,ctrlid
130#parentTitle:None,hwnd,text,class
131def findWindow(title, parentTitle = None, isRaw = False):
132hwndList = findWindows(title, parentTitle, isRaw)
133if hwndList:
134return hwndList[0]
135def findRawWindows(title, parentTitle = None):
136return findWindows(title, parentTitle, True)
137 
138#判断是否为非正常窗口
139def isRawWindow(hwnd):
140return not win32gui.IsWindowVisible(hwnd) or not win32gui.IsWindowEnabled(hwnd) or ctypes.windll.user32.IsHungAppWindow(hwnd)
141 
142#查找窗口
143#title:text,class,ctrlid
144#parentTitle:None,hwnd,text,class
145def findWindows(title, parentTitle = None, isRaw = False):
146def __enumWindowHandler__(hwnd, wndList):
147text = re.split('[\r|\n]+', getWindowText(hwnd))[0].strip()
148clazz = getWindowClass(hwnd).strip()
149ctrlId = win32gui.GetDlgCtrlID(hwnd)
150wndList.append((hwnd, text, clazz, ctrlId))
151if not parentTitle:
152parentHwndList = [None]
153elif type(parentTitle) == int:
154parentHwndList = [parentTitle]
155else:
156parentHwndList = findRawWindows(parentTitle)
157hwndSet = set()
158for parentHwnd in parentHwndList:
159wndList = []
160#EnumWindows
161if parentHwnd:
162tryExcept(win32gui.EnumChildWindows, parentHwnd, __enumWindowHandler__, wndList)
163else:
164win32gui.EnumWindows(__enumWindowHandler__, wndList)
165#FindWindowEx
166hwnd, foundHwndList = None, []
167while True:
168hwnd = tryExcept(win32gui.FindWindowEx, parentHwnd, hwnd, None, None)
169if not hwnd or isExcept(hwnd) or hwnd in foundHwndList:
170break
171__enumWindowHandler__(hwnd, wndList)
172foundHwndList.append(hwnd)
173#GetWindow
174if parentHwnd:
175hwnd = tryExcept(win32gui.GetWindow, parentHwnd, win32con.GW_CHILD)
176else:
177hwnd = tryExcept(win32gui.GetWindow, win32gui.GetDesktopWindow(), win32con.GW_CHILD)
178while hwnd and not isExcept(hwnd):
179__enumWindowHandler__(hwnd, wndList)
180hwnd = tryExcept(win32gui.GetWindow, hwnd, win32con.GW_HWNDNEXT)
181#Combine
182for hwnd, text, clazz, ctrlId in set(wndList):
183if type(title) == int:
184if ctrlId == title:
185hwndSet.add(hwnd)
186elif text == title or re.match('^' + title + '$', text, re.S) or clazz == title or re.match('^' + title + '$', clazz, re.S):
187hwndSet.add(hwnd)
188if parentHwnd:
189hwndSet.update(findRawWindows(title, hwnd))
190if isRaw:
191return list(hwndSet)
192hwndList = []
193for hwnd in hwndSet:
194if not isRawWindow(hwnd):
195hwndList.append(hwnd)
196return hwndList
197 
198#设置窗口文字
199def setWindowText(hwnd, text):
200rst = tryExcept(win32gui.SendMessageTimeout, hwnd, win32con.WM_SETTEXT, 0, text, win32con.SMTO_ABORTIFHUNG, 10)
201return not isExcept(rst)
202 
203#杀掉指定name的进程
204def killProcessByName(pname, user = None):
205killProcessByNames([pname], user)
206 
207def listFile(path, isDeep=True):
208_list = []
209if isDeep:
210try:
211for root, dirs, files in os.walk(path):
212for fl in files:
213_list.append('%s\%s' % (root, fl))
214except:
215pass
216else:
217for fn in glob.glob( path + os.sep + '*' ):
218if not os.path.isdir(fn):
219_list.append('%s' % path + os.sep + fn[fn.rfind('\\')+1:])
220return _list
221 
222 
223#杀掉指定name的进程列表
224def killProcessByNames(pnameList, user = None):
225cmd = 'taskkill /F /T'
226if user:
227cmd += ' /FI "USERNAME eq %s"' % user
228for pname in pnameList:
229cmd += ' /IM %s' % pname
230createProcess(cmd, True)
231 
232#超时设置
233def handleTimeout(func, timeout, *params, **paramMap):
234interval = 0.8
235if type(timeout) == tuple:
236timeout, interval = timeout
237while timeout > 0:
238t = time.time()
239rst = func(*params, **paramMap)
240if rst and not isExcept(rst):
241break
242time.sleep(interval)
243timeout -= time.time() - t
244return rst
245 
246#写文件
247def setFileData(filename, data, mode):
248f = open(filename, mode)
249f.write(data)
250f.close()
251 
252 
253if __name__ == '__main__':
254if os.path.isfile('md5.log'):
255os.system('del md5.log')
256 
257parentHwnd = r'Hash.*?'
258#setWindowText(textblack,'123')
259filedir = os.path.join(os.getcwd(),'needCheck')
260filelist = listFile(filedir)
261#os.chdir(filedir)
262 
263for file in filelist:
264#启进程
265createProcess('Hash.exe')
266#查找浏览按钮
267browse_button = findWindow(r'浏览.*?',parentHwnd)
268#点击浏览按钮
269clickWindow(browse_button)
270textblack = findWindow(0x47C,'#32770')
271handleTimeout(setWindowText,10,textblack,file)
272open_hwnd = findWindow('打开.*?','#32770')
273#点击打开按钮
274clickWindow(open_hwnd)
275#获取文件md5信息
276#需要内容的行号
277expect_content_id = [0,4]
278content_hwnd = findWindow(0x3EA,r'Hash.*?')
279content_text = handleTimeout(getWindowText,20,content_hwnd)
280content = content_text.split('\r\n')
281md5content = [i.split(': ')[1].strip() for ind, i in enumerate(content) if ind in expect_content_id]
282print md5content
283filename,md5value = md5content
284setFileData('md5.log','文件名:'+filename+'\n'+'md5:'+ md5value+'\n\n','a')
285killProcessByName('Hash.exe')
286os.system('pause')

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值