python自动测试r_使用python进行windows自动化测试(1)

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

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

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

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

工具下载

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

测试的目录结构

--automd5--

--needCheck--

checkmd5.py

SpyLite24.exe

Hash.exe

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

#! /usr/bin/env python

#coding=gbk

import time,re,ctypes

import os,sys,subprocess,win32gui,win32con,win32api

import glob,time

#启进程函数

def createProcess(cmd, wait = False):

if wait:

proc = tryExcept(subprocess.Popen, cmd, stdout = subprocess.PIPE, stderr = subprocess.PIPE)

else:

proc = tryExcept(subprocess.Popen, cmd)

if isExcept(proc):

return

if not wait:

return proc.pid

proc.communicate()

def tryExcept(func, *params, **paramMap):

try:

return func(*params, **paramMap)

except Exception, e:

return e

def isExcept(e, eType = Exception):

return isinstance(e, eType)

class BaseWindow:

@staticmethod

def parseClickConfig(clkCfg):

if clkCfg == None:

return None, None, False, 0

if type(clkCfg) == bool:

return None, None, clkCfg, 0

if type(clkCfg) == int:

return None, None, False, clkCfg

if len(clkCfg) == 2:

if type(clkCfg[0]) == int and type(clkCfg[1]) == int:

return clkCfg[0], clkCfg[1], False, 0

return None, None, clkCfg[0], clkCfg[1]

if len(clkCfg) == 3:

if type(clkCfg[2]) == bool:

return clkCfg[0], clkCfg[1], clkCfg[2], 0

return clkCfg[0], clkCfg[1], False, clkCfg[2]

return clkCfg

#点击窗口

#clkCfg:byDrv|mode|(x,y)|(byDrv,mode)|(x,y,byDrv)|(x,y,mode)|(x,y,byDrv,mode)

def clickWindow(hwnd, clkCfg = None):

if isRawWindow(hwnd):

return

topWindow(hwnd)

rect = getWindowRect(hwnd)

if not rect:

return

x, y, byDrv, mode = BaseWindow.parseClickConfig(clkCfg)

if x == None:

x = (rect[0] + rect[2]) / 2

elif x < 0:

x += rect[2]

else:

x += rect[0]

if y == None:

y = (rect[1] + rect[3]) / 2

elif y < 0:

y += rect[3]

else:

y += rect[1]

clickMouse(x, y, byDrv, mode)

#点击鼠标

CLICK_MOUSE = 0

CLICK_MOUSE_DOUBLE = 1

CLICK_MOUSE_RIGHT = 2

def clickMouse(x, y, byDrv = False, mode = CLICK_MOUSE):

moveMouse(x, y, byDrv)

downMsg, upMsg = win32con.MOUSEEVENTF_LEFTDOWN, win32con.MOUSEEVENTF_LEFTUP

if mode == CLICK_MOUSE_RIGHT:

downMsg, upMsg = win32con.MOUSEEVENTF_RIGHTDOWN, win32con.MOUSEEVENTF_RIGHTUP

win32api.mouse_event(downMsg, 0, 0, 0, 0)

win32api.mouse_event(upMsg, 0, 0, 0, 0)

if mode == CLICK_MOUSE_DOUBLE:

win32api.mouse_event(downMsg, 0, 0, 0, 0)

win32api.mouse_event(upMsg, 0, 0, 0, 0)

#移动鼠标

def moveMouse(x, y, byDrv = False):

w, h = win32api.GetSystemMetrics(0), win32api.GetSystemMetrics(1)

x, y = int(float(x) / w * 65535), int(float(y) / h * 65535)

win32api.mouse_event(win32con.MOUSEEVENTF_MOVE | win32con.MOUSEEVENTF_ABSOLUTE, x, y, 0, 0)

#获得窗口尺寸

def getWindowRect(hwnd):

rect = tryExcept(win32gui.GetWindowRect, hwnd)

if not isExcept(rect):

return rect

#置顶窗口

def topWindow(hwnd):

fgHwnd = win32gui.GetForegroundWindow()

if fgHwnd == hwnd:

return True

rst = tryExcept(win32gui.SetForegroundWindow, hwnd)

if not isExcept(rst):

return True

return getWindowClass(fgHwnd) == 'Progman' and getWindowText(fgHwnd) == 'Program Manager'

##获取窗口文字

def getWindowText(hwnd, buf = ctypes.c_buffer(1024)):

size = ctypes.sizeof(buf)

ctypes.memset(buf, 0, size)

tryExcept(win32gui.SendMessageTimeout, hwnd, win32con.WM_GETTEXT, size, buf, win32con.SMTO_ABORTIFHUNG, 10)

return buf.value.strip()

#获取窗口类名

def getWindowClass(hwnd, buf = ctypes.c_buffer(1024)):

size = ctypes.sizeof(buf)

ctypes.memset(buf, 0, size)

ctypes.windll.user32.GetClassNameA(hwnd, ctypes.addressof(buf), size)

return buf.value.strip()

#查找第一个窗口

#title:text,class,ctrlid

#parentTitle:None,hwnd,text,class

def findWindow(title, parentTitle = None, isRaw = False):

hwndList = findWindows(title, parentTitle, isRaw)

if hwndList:

return hwndList[0]

def findRawWindows(title, parentTitle = None):

return findWindows(title, parentTitle, True)

#判断是否为非正常窗口

def isRawWindow(hwnd):

return not win32gui.IsWindowVisible(hwnd) or not win32gui.IsWindowEnabled(hwnd) or ctypes.windll.user32.IsHungAppWindow(hwnd)

#查找窗口

#title:text,class,ctrlid

#parentTitle:None,hwnd,text,class

def findWindows(title, parentTitle = None, isRaw = False):

def __enumWindowHandler__(hwnd, wndList):

text = re.split('[\r|\n]+', getWindowText(hwnd))[0].strip()

clazz = getWindowClass(hwnd).strip()

ctrlId = win32gui.GetDlgCtrlID(hwnd)

wndList.append((hwnd, text, clazz, ctrlId))

if not parentTitle:

parentHwndList = [None]

elif type(parentTitle) == int:

parentHwndList = [parentTitle]

else:

parentHwndList = findRawWindows(parentTitle)

hwndSet = set()

for parentHwnd in parentHwndList:

wndList = []

#EnumWindows

if parentHwnd:

tryExcept(win32gui.EnumChildWindows, parentHwnd, __enumWindowHandler__, wndList)

else:

win32gui.EnumWindows(__enumWindowHandler__, wndList)

#FindWindowEx

hwnd, foundHwndList = None, []

while True:

hwnd = tryExcept(win32gui.FindWindowEx, parentHwnd, hwnd, None, None)

if not hwnd or isExcept(hwnd) or hwnd in foundHwndList:

break

__enumWindowHandler__(hwnd, wndList)

foundHwndList.append(hwnd)

#GetWindow

if parentHwnd:

hwnd = tryExcept(win32gui.GetWindow, parentHwnd, win32con.GW_CHILD)

else:

hwnd = tryExcept(win32gui.GetWindow, win32gui.GetDesktopWindow(), win32con.GW_CHILD)

while hwnd and not isExcept(hwnd):

__enumWindowHandler__(hwnd, wndList)

hwnd = tryExcept(win32gui.GetWindow, hwnd, win32con.GW_HWNDNEXT)

#Combine

for hwnd, text, clazz, ctrlId in set(wndList):

if type(title) == int:

if ctrlId == title:

hwndSet.add(hwnd)

elif text == title or re.match('^' + title + '$', text, re.S) or clazz == title or re.match('^' + title + '$', clazz, re.S):

hwndSet.add(hwnd)

if parentHwnd:

hwndSet.update(findRawWindows(title, hwnd))

if isRaw:

return list(hwndSet)

hwndList = []

for hwnd in hwndSet:

if not isRawWindow(hwnd):

hwndList.append(hwnd)

return hwndList

#设置窗口文字

def setWindowText(hwnd, text):

rst = tryExcept(win32gui.SendMessageTimeout, hwnd, win32con.WM_SETTEXT, 0, text, win32con.SMTO_ABORTIFHUNG, 10)

return not isExcept(rst)

#杀掉指定name的进程

def killProcessByName(pname, user = None):

killProcessByNames([pname], user)

def listFile(path, isDeep=True):

_list = []

if isDeep:

try:

for root, dirs, files in os.walk(path):

for fl in files:

_list.append('%s\%s' % (root, fl))

except:

pass

else:

for fn in glob.glob( path + os.sep + '*' ):

if not os.path.isdir(fn):

_list.append('%s' % path + os.sep + fn[fn.rfind('\\')+1:])

return _list

#杀掉指定name的进程列表

def killProcessByNames(pnameList, user = None):

cmd = 'taskkill /F /T'

if user:

cmd += ' /FI "USERNAME eq %s"' % user

for pname in pnameList:

cmd += ' /IM %s' % pname

createProcess(cmd, True)

#超时设置

def handleTimeout(func, timeout, *params, **paramMap):

interval = 0.8

if type(timeout) == tuple:

timeout, interval = timeout

while timeout > 0:

t = time.time()

rst = func(*params, **paramMap)

if rst and not isExcept(rst):

break

time.sleep(interval)

timeout -= time.time() - t

return rst

#写文件

def setFileData(filename, data, mode):

f = open(filename, mode)

f.write(data)

f.close()

if __name__ == '__main__':

if os.path.isfile('md5.log'):

os.system('del md5.log')

parentHwnd = r'Hash.*?'

#setWindowText(textblack,'123')

filedir = os.path.join(os.getcwd(),'needCheck')

filelist = listFile(filedir)

#os.chdir(filedir)

for file in filelist:

#启进程

createProcess('Hash.exe')

#查找浏览按钮

browse_button = findWindow(r'浏览.*?',parentHwnd)

#点击浏览按钮

clickWindow(browse_button)

textblack = findWindow(0x47C,'#32770')

handleTimeout(setWindowText,10,textblack,file)

open_hwnd = findWindow('打开.*?','#32770')

#点击打开按钮

clickWindow(open_hwnd)

#获取文件md5信息

#需要内容的行号

expect_content_id = [0,4]

content_hwnd = findWindow(0x3EA,r'Hash.*?')

content_text = handleTimeout(getWindowText,20,content_hwnd)

content = content_text.split('\r\n')

md5content = [i.split(': ')[1].strip() for ind, i in enumerate(content) if ind in expect_content_id]

print md5content

filename,md5value = md5content

setFileData('md5.log','文件名:'+filename+'\n'+'md5:'+ md5value+'\n\n','a')

killProcessByName('Hash.exe')

os.system('pause')

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值