关键字驱动测试框架搭建(3)

关键字驱动测试框架搭建(3)
关键字驱动的完整框架:
在Pycharm中创建一Python工程,其下再创建Util包,action包,config包,testScripts包,log目录,testData目录,exceptionPictures目录,具体内容如下:
Util包中存放封装的常用函数:
ParseExcel.py 解析Excel

#encoding=utf-8
import openpyxl
from openpyxl.styles import Border,Side,Font
import time

class ParseExcel(object):
    def __init__(self):
        self.workbook = None
        self.excelFile = None
        self.font = Font(color = None) #设置字体的颜色
        self.RGBDict = {"red":"FFFF3030","green":"FF008B00"}

    def loadWorkbook(self,excelPathAndName):
        #将excel加载到内存,并获取其workbook对象
        try:
            self.workbook = openpyxl.load_workbook(excelPathAndName)
        except Exception,e:
            raise e
        self.excelFile = excelPathAndName
        return self.workbook

    def getSheetByName(self,sheetName):
        #要报sheet名称获取sheet对象
        try:
            sheet = self.workbook.get_sheet_by_name(sheetName)
            return sheet
        except Exception,e:
            raise e

    def getSheetByIndex(self,sheetIndex):
        #根据sheet的索引号获取sheet对象
        try:
            sheetname = self.workbook.get_sheet_names()[sheetIndex]
        except Exception,e:
            raise e
        sheet = self.workbook.get_sheet_by_name(sheetname)
        return sheet

    def getRowsNumber(self,sheet):
        #获取sheet中有数据区域的结束行号
        return sheet.max_row

    def getColsNumber(self,sheet):
        #获取sheet中有数据区域的结束列号
        return sheet.max_column

    def getStartRowNumber(self,sheet):
        #获取sheet中有数据区域的开通行号
        return sheet.min_row

    def getStartColNumber(self,sheet):
        #获取sheet中有数据区域的开始列号
        return sheet.min_column

    def getRow(self,sheet,rowNo):
        #获取sheet中的某一行,返回的是这一行所有的数据内容组成的tuple
        #下标从1开始,sheet.rows[1]表示第一行
        try:
            rows = []
            for row in sheet.iter_rows():
                rows.append(row)
            return rows[rowNo-1]
        except Exception,e:
            raise e

    def getColumn(self,sheet,colNo):
        #获取sheet中的某一列,返回的是这一列所有的数据内容组成的tuple
        # 下标从1开始,sheet.cols[1]表示第一列
        try:
            cols = []
            for col in sheet.iter_cols():
                cols.append(col)
            return cols[colNo-1]
        except Exception,e:
            raise e

    def getCellOfValue(self,sheet,coordinate = None,rowNo = None,colNo = None):
        #要报单元格所在的索引位置获取该单元格的值,下标从1开始
        #sheet.cell(row=1,column=1).value,表示 excel中第一行第一列的值
        if coordinate != None:
            try:
                return sheet.cell(coordinate = coordinate).value
            except Exception,e:
                raise e
        elif coordinate == None is None and rowNo is not None and colNo is not None:
            try:
                return sheet.cell(row = rowNo,column = colNo).value
            except Exception,e:
                raise e
        else:
            raise Exception("Insufficient Coordinate of cell")

    def getCellOfObject(self,sheet,coordinate = None,rowNo = None,colNo = None):
        #获取某个单元格对象,可以通过单元格的位置索引,也可以通过Excel单元格的编码坐标、,
        #如 getCellOfObject(sheet,coordinate = "A1")  , 或getCellOfObject(sheet,rowNo=1,colNo=1)
        if coordinate != None:
            try:
                return sheet.cell(coordinate = coordinate)
            except Exception,e:
                raise e
        elif coordinate == None and rowNo is not None and colNo is not None:
            try:
                return sheet.cell(row = rowNo,column = colNo)
            except Exception,e:
                raise e
        else:
            raise Exception("Insufficient Coordinate of cell")

    def writeCell(self,sheet,content,coordinate = None,rowNo = None,colNo = None,style = None):
        #根据单元格在excel中的编码坐标或数字索引坐标向单元 格中写入数据
        #下标从1开始,参数style表示字体的颜色的名称,red green
        if coordinate is not None:
            try:
                sheet.cell(coordinate = coordinate).value = content
                if style is not None:
                    sheet.cell(coordinate = coordinate).font = Font(color = self.RGBDict[style])
                self.workbook.save(self.excelFile)
            except Exception,e:
                raise e
        if coordinate == None and rowNo is not None and colNo is not None:
            try:
                sheet.cell(row = rowNo,column = colNo).value  = content
                if style is not None:
                   sheet.cell(coordinate=coordinate).font = Font(color=self.RGBDict[style])
                self.workbook.save(self.excelFile)
            except Exception,e:
                raise e
        else:
            raise Exception("Insufficient Coordinate of cell")

    def writeCellCurrentTime(self,sheet,coordinate = None,rowNo = None,colNo = None):
        #写入当前时间
        now = int(time.time())
        timeArray = time.localtime(now)
        currentTime = time.strftime("%Y-%m-%d %H:%M:%S",timeArray)
        if coordinate != None:
            try:
                sheet.cell(coordinate = coordinate).value = currentTime
                self.workbook.save(self.excelFile)
            except Exception,e:
                raise e
        elif coordinate == None and rowNo is not None and colNo is not None:
            try:
                sheet.cell(row = rowNo,column = colNo).value = currentTime
                self.workbook.save(self.excelFile)
            except Exception,e:
                raise e
        else:
            raise Exception("Insufficient Coordinate of cell")

if __name__ == "__main__":
    pe = ParseExcel()
    pe.loadWorkbook("D:\\test\\test.xlsx")
    print u"通过名称获取sheet对象的名字:",pe.getSheetByName("test2").title
    print u"通过序号获取sheet对象的名字:",pe.getSheetByIndex(0).title
    sheet = pe.getSheetByIndex(1)
    print type(sheet)
    print u"最大行号:",pe.getRowsNumber(sheet)
    print u"最大列号:",pe.getColsNumber(sheet)
    row = pe.getRow(sheet,2) #获取第二行
    print row
    for i in row:
        print i.value

    print pe.getCellOfValue(sheet,rowNo = 1,colNo = 1)
    pe.writeCell(sheet,u"I love Python代码",rowNo = 10,colNo= 10)
    pe.writeCellCurrentTime(sheet,rowNo = 10,colNo = 11)
    print pe.getCellOfValue(sheet,rowNo = 10,colNo = 10)
    print pe.getCellOfValue(sheet,rowNo = 10,colNo = 11)

DirAndTime.py 封装时间和异常截图目录

#encoding=utf-8
import os,time
from datetime import datetime
from config.VarConfig import screenPicturesDir

#获取当前日期
def getCurrentDate():
    timeTup = time.localtime()
    currentDate = str(timeTup.tm_year) + "-" + str(timeTup.tm_mon) + "-" + str(timeTup.tm_mday)
    return currentDate

#获取当前的时间
def getCurrentTime():
    timeStr = datetime.now()
    nowTime = timeStr.strftime("%H:%M:%S")
    return  nowTime

#创建截图存放的目录
def createCurrentDateDir():
    dirName = os.path.join(screenPicturesDir,getCurrentDate())
    if not os.path.exists(dirName):
        os.mkdir(dirName)
    return dirName

if __name__ == "__main__":
    print getCurrentDate()
    print getCurrentTime()
    print createCurrentDateDir()

log.py 封装日志

#encoding=utf-8
import logging
import logging.config
from config.VarConfig import parentDirPath

#读取日志配置文件
logging.config.fileConfig(parentDirPath + u"\\config\\Logger.conf")

#选择一个日志格式
logger = logging.getLogger("example01")

def debug(message):
    #定义debug级别日志打印方法
    logger.debug(message)

def info(message):
    #定义info级别日志打印方法
    logger.info(message)

def warning(message):
    #定义warning级别日志打印方法
    logger.warning(message)

ObjectMap.py  封装获取页面元素方法

#encoding=utf-8
from selenium.webdriver.support.ui import WebDriverWait

#获取单个页面元素
def getElement(driver,locationType,locatorExpression):
    try:
        element = WebDriverWait(driver,30).until(lambda x:x.find_element(by = locationType,value = locatorExpression))
        return element
    except Exception,e:
        raise e

#获取多个相同页面元素对象,以list返回
def getElements(driver,locationType,locatorExpression):
    try:
        elements = WebDriverWait(driver,30).until(lambda x:x.find_elements(by = locationType,value = locatorExpression))
        return elements
    except Exception,e:
        raise e

if __name__ == "__main__":
    from selenium import webdriver
    #进行单元测试
    driver = webdriver.Firefox(executable_path="D:\\geckodriver")
    driver.get("http://www.baidu.com")
    searchBox = getElement(driver,"id","kw")
    #打印页面对象的标签名
    print searchBox.tag_name
    aList = getElements(driver,"tag name","a")
    print len(aList)
    driver.quit()

WaitUtil.py 封装等待类

#encoding=utf-8
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

class WaitUtil(object):
    def __init__(self,driver):
        self.locationTypeDict = {
            "xpath":By.XPATH,
            "id":By.ID,
            "name":By.NAME,
            "css_selector":By.CSS_SELECTOR,
            "class_name":By.CLASS_NAME,
            "tag_name":By.TAG_NAME,
            "link_text":By.LINK_TEXT,
            "partial_link_text":By.PARTIAL_LINK_TEXT,
        }
        self.driver = driver
        self.wait = WebDriverWait(driver,30)

    def presenceOfElementLocated(self,locatorMethod,locatorExpression,*args):
        """显式等待页面元素出现在DOM中,但并不一定可见,存在则返回该页面元素"""
        try:
            if self.locationTypeDict.has_key(locatorMethod.lower()):
                self.wait.until(EC.presence_of_element_located((self.locationTypeDict[locatorMethod.lower()],locatorExpression)))
            else:
                raise Exception(u"未找到定位方式,请确认定位方式是否书写正确")
        except Exception,e:
            raise e

    def frameToBeAvailableAndSwitchToIt(self,locationType,locatorExpression,*args):
        """检查frame是否存在,存在则切换进frame控件中"""
        try:
            self.wait.until(EC.frame_to_be_available_and_switch_to_it((self.locationTypeDict[locationType.lower()],locatorExpression)))
        except Exception,e:
            raise e

    def visibilityOfElementLocated(self,locationMethod,locatorExperssion,*args):
        """显式等待页面元素出现在DOM中,并且可见,存在则返回该页面元素对象"""
        try:
            self.wait.until(EC.visibility_of_element_located((self.locationTypeDict[locationMethod.lower()],locatorExperssion)))
        except Exception,e:
            raise e

if __name__ == "__main__":
    from selenium import webdriver
    driver = webdriver.Firefox(executable_path = "D:\\geckodriver")
    driver.get("https://mail.126.com/")
    waitUtil = WaitUtil(driver)
    driver.find_element_by_id("lbNormal").click()
    # waitUtil.presenceOfElementLocated("id","lbNormal")
    waitUtil.frameToBeAvailableAndSwitchToIt("xpath",'//iframe[contains(@id,"x-URS-iframe")]')
    waitUtil.visibilityOfElementLocated("xpath","//input[@name='email']")
    waitUtil.presenceOfElementLocated("xpath","//input[@name='email']")
    driver.quit()

ClipboardUtil.py  封装操作剪切板方法

#encoding=utf-8
import win32clipboard as w
import win32con

class Clipboard(object):
    """模拟windows设置剪切板"""
    #读取剪切板
    @staticmethod
    def getText():
        #打开剪切板
        w.OpenClipboard()
        #获取剪切板中的数据
        d = w.GetClipboardData(win32con.CF_TEXT)
        #关闭剪切板
        w.CloseClipboard()
        #返回剪切板数据给调用者
        return d

    #设置剪切板内容
    @staticmethod
    def setText(aString):
        #打开剪切板
        w.OpenClipboard()
        #清空剪切板
        w.EmptyClipboard()
        #将数据aString写入剪切板
        w.SetClipboardData(win32con.CF_UNICODETEXT,aString)
        #关闭剪切板
        w.CloseClipboard()

KeyBoardUtil.py 封装键盘按键方法

#encoding=utf-8
import win32con
import win32api

class KeyBoardKeys(object):
    """模拟键盘按键类"""
    VK_CODE = {
        'enter': 0x0D,
        'ctrl': 0x11,
        'v': 0x56
    }

    @staticmethod
    def keyDown(keyName):
        #按下按键
        win32api.keybd_event(KeyBoardKeys.VK_CODE[keyName],0,0,0)

    @staticmethod
    def keyUp(keyName):
        #释放按键
        win32api.keybd_event(KeyBoardKeys.VK_CODE[keyName],0,win32con.KEYEVENTF_KEYUP,0)

    @staticmethod
    def oneKey(key):
        #模拟单个按键
        KeyBoardKeys.keyDown(key)
        KeyBoardKeys.keyUp(key)

    @staticmethod
    def twoKeys(key1,key2):
        KeyBoardKeys.keyDown(key1)
        KeyBoardKeys.keyDown(key2)
        KeyBoardKeys.keyUp(key2)
        KeyBoardKeys.keyUp(key1)

config包存放日志配置文件和变量:
Logger.conf

#logger.conf
###############################################
[loggers]
keys=root,example01,example02
[logger_root]
level=DEBUG
handlers=hand01,hand02

[logger_example01]
handlers=hand01,hand02
qualname=example01
propagate=0

[logger_example02]
handlers=hand01,hand03
qualname=example02
propagate=0

###############################################
[handlers]
keys=hand01,hand02,hand03

[handler_hand01]
class=StreamHandler
level=INFO
formatter=form01
args=(sys.stderr,)

[handler_hand02]
class=FileHandler
level=DEBUG
formatter=form01
args=('log\\Mail126TestLogfile.log', 'a')

[handler_hand03]
class=handlers.RotatingFileHandler
level=INFO
formatter=form01
args=('log\\Mail126TestLogfile.log', 'a', 10*1024*1024, 5)

###############################################
[formatters]
keys=form01,form02

[formatter_form01]
format=%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s
datefmt=%Y-%m-%d %H:%M:%S

[formatter_form02]
format=%(name)-12s: %(levelname)-8s %(message)s
datefmt=%Y-%m-%d %H:%M:%S

VarConfig.py 存放变量

#encoding=utf-8
import os

ieDriverFilePath = "D:\\IEDriverServer"
chromeDriverFilePath = "D:\\chromedriver"
firefoxDriverFilePath = "D:\\geckodriver"

#当前文件所在目录的父目录的绝对路径
parentDirPath = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

#异常截图存放目录绝对路径
screenPicturesDir = parentDirPath + u"\\exceptionpictures"

#测试数据文件存放的绝对路径
dataFilePath = parentDirPath + u"\\testData\\126邮箱发送邮件.xlsx"

# 测试数据文件中,测试用例表中部分列对应的数字序号
testCase_testCaseName = 2
testCase_testStepSheetName = 4
testCase_isExecute = 5
testCase_runTime = 6
testCase_testResult = 7

# 用例步骤表中,部分列对应的数字序号
testStep_testStepDescribe = 2
testStep_keyWords = 3
testStep_locationType = 4
testStep_locatorExpression = 5
testStep_operateValue = 6
testStep_runTime = 7
testStep_testResult = 8
testStep_errorInfo = 9
testStep_errorPic = 10

testData目录下存放测试数据,26邮箱发送邮件.xlsx
sheet--测试用例            
序号    用例名称         用例描述                             步骤sheet名             是否执行           执行结束时间            结果
1    登录126邮箱             使用有效的账号登录126邮箱                 登录                      y    
2    发送带附件的邮件    登录126邮箱后,发送一封带附件的邮件         发邮件                      y    

sheet--登录
序号    测试步骤描述    关键字    操作元素的定位方式    操作元素的定位表达式    操作值    测试执行时间    测试结果    错误信息    错误截图
1         打开浏览器    open_browser            chrome                
2        访问被测试网址http://www.126.com    visit_url            http://www.126.com                
3        最大化窗口    maximize_browser                            
4        等待126邮箱登录主页加载完成    sleep            5                
5        断言当前活动页面源码中是否包含“126网易免费邮--你的专业电子邮局”    assert_string_in_pagesource            126网易免费邮--你的专业电子邮局                
6        显示等待id属性值为x-URS-iframe的frame框的出现,然后切换进入该frame框中    waitFrameToBeAvailableAndSwitchToIt    id    x-URS-iframe                    
7        输入登录用户名    input_string    xpath    //input[@name='email']    xxxx
8        输入登录密码    input_string    xpath    //input[@name='password']    xxxx
9        点击登录按钮    click    id    dologin                    
10        等待    sleep            5                
11        切回默认会话窗体    switch_to_default_content                            
12    断言登录成功后的页面标题是否包含“网易邮箱6.0版”关键内容    assert_title            网易邮箱6.0版                


sheet--发邮件
序号    测试步骤描述    关键字    操作元素的定位方式    操作元素的定位表达式    操作值    测试执行时间    测试结果    错误信息    错误截图
1    判断“写信”按钮是否在页面上可见    waitVisibilityOfElementLocated    xpath    //span[text()='写 信']                    
2    点击“写信”按钮    click    xpath    //span[text()='写 信']                    
3    输入收件人地址    input_string    xpath    //div[contains(@id,'_mail_emailinput')]/input    xxx@126.com                
4    输入邮件主题    input_string    xpath    //div[@aria-label='邮件主题输入框,请输入邮件主题']/input    带附件的邮件                
5    点击“上传附件”链接    click    xpath    // div[contains( @ title, '点击添加附件')]                    
6    输入附件所在绝对路径    paste_string            D:\\test\\test.txt                
7    模拟键盘回车键    press_enter_key                            
8    显示等待附件上传完毕    waitVisibilityOfElementLocated    xpath    //span[text()="上传完成"]                    
9    如果邮件正文的frame框是否可见,切换进该frame中    waitFrameToBeAvailableAndSwitchToIt    xpath    //iframe[@tabindex=1]                    
10    输入邮件正文    input_string    xpath    /html/body    发给光荣之路的一封信                
11    退出邮件正文的frame    switch_to_default_content                            
12    点击邮件发送按钮    click    xpath    //header//span[text()='发送']                    
13    等待邮件发送成功,返回结果    sleep            3                
14    断言页面源码中是否出现“发送成功”关键内容    assert_string_in_pagesource            发送成功                
15    关闭浏览器    close_browser                            


创建log目录,存放日志文件
创建exceptionpictures目录,存放异常截图
创建action包,存放关键字对应的方法
PageAction.py

#encoding=utf-8
from selenium import webdriver
from config.VarConfig import ieDriverFilePath
from config.VarConfig import chromeDriverFilePath
from config.VarConfig import firefoxDriverFilePath
from Util.ObjectMap import getElement
from Util.KeyBoardUtil import KeyBoardKeys
from Util.ClipboardUtil import Clipboard
from Util.DirAndTime import *
from Util.WaitUtil import WaitUtil
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.chrome.options import Options
import time

#定义全局变量driver
driver = None
#定义全局的等待类实例对象
waitUtil = None

def open_browser(browserName,*args):
    #打开浏览器
    global driver,waitUtil
    try:
        if browserName.lower() == "ie":
            driver = webdriver.Ie(executable_path = ieDriverFilePath)
        elif browserName.lower == "chrome":
            #创建Chrome浏览器的一个Options实例对象
            chrome_options = Options()
            #添加屏蔽--ignore--certificate--errors提示信息的设置参数项
            chrome_options.add_experimental_option("excludeSwitches",["ignore-certificate-errors"])
            driver = webdriver.Chrome(executable_path = chromeDriverFilePath,chrome_options = chrome_options)
        else:
            driver = webdriver.Firefox(executable_path = firefoxDriverFilePath)
        #driver对象创建成功后,创建等待类实例对象
        waitUtil = WaitUtil(driver)
    except Exception,e:
        raise e

def visit_url(url,*args):
    #访问某个网站
    global driver
    try:
        driver.get(url)
    except Exception,e:
        raise e

def close_browser(*args):
    #关闭浏览器
    global driver
    try:
        driver.quit()
    except Exception,e:
        raise e

def sleep(sleepSeconds,*args):
    #强制等待
    try:
        time.sleep(int(sleepSeconds))
    except Exception,e:
        raise e

def clear(locationType,locatorExpression,*args):
    #清空输入框默认内容
    global driver
    try:
        getElement(driver,locationType,locatorExpression).clear()
    except Exception,e:
        raise e

def input_string(locationType,locatorExpression,inputContent):
    #在页面输入框中输入数据
    global driver
    try:
        getElement(driver,locationType,locatorExpression).send_keys(inputContent)
    except Exception,e:
        raise e

def click(locationType,locatorExpression,*args):
    #点击页面元素
    global driver
    try:
        getElement(driver,locationType,locatorExpression).click()
    except Exception,e:
        raise e

def assert_string_in_pagesource(assertString,*args):
    #断言页面源码是否存在某个关键字或关键字符串
    global driver
    try:
        assert assertString in driver.page_source,u"%s not found in page source!" % assertString
    except AssertionError,e:
        raise AssertionError(e)
    except Exception,e:
        raise e

def assert_title(titleStr,*args):
    #断言页面标题是否存在给定的关键字符串
    global driver
    try:
        assert titleStr in driver.title,u"%s not found in page title!" % titleStr
    except AssertionError,e:
        raise AssertionError(e)
    except Exception,e:
        raise e

def getTitle(*args):
    #获取页面标题
    global driver
    try:
        return driver.title
    except Exception,e:
        raise e

def getPageSource(*args):
    #获取页面源码
    global driver
    try:
        return driver.page_source
    except Exception,e:
        raise e

def switch_to_frame(locationType,frameLocatorExpressoin,*args):
    #切换进frame
    global driver
    try:
        driver.switch_to.frame(getElement(driver,locationType,frameLocatorExpressoin))
    except Exception,e:
        print "frame error!"
        raise e

def switch_to_default_content(*args):
    #切换妯frame
    global driver
    try:
        driver.switch_to.default_content()
    except Exception,e:
        raise e

def paste_string(pasteString,*args):
    #模拟Ctrl+V操作
    try:
        Clipboard.setText(pasteString)
        #等待2秒,防止代码执行过快,而未成功粘贴内容
        time.sleep(2)
        KeyBoardKeys.twoKeys("ctrl","v")
    except Exception,e:
        raise e

def press_tab_key(*args):
    #模拟tab键
    try:
        KeyBoardKeys.oneKey("tab")
    except Exception,e:
        raise e

def press_enter_key(*args):
    #模拟enter键
    try:
        KeyBoardKeys.oneKey("enter")
    except Exception,e:
        raise e

def maximize_browser(*args):
    #窗口最大化
    global driver
    try:
        driver.maximize_window()
    except Exception,e:
        raise e

def capture_screen(*args):
    #截取屏幕图片
    global driver
    currentTiem = getCurrentTime()
    picNameAndPath = str(createCurrentDateDir()) + "\\" + str(currentTiem) + ".png"
    try:
        driver.get_screenshot_as_file(picNameAndPath.replace(("\\",r"\\")))
    except Exception,e:
        raise e
    else:
        return picNameAndPath

def waitPresenceOfElementLocated(locationType,locatorExpression,*args):
    """显式等待页面元素出现在DOM中,但不一定可见,存在则返回该页面元素对象"""
    global waitUtil
    try:
        waitUtil.presenceOfElementLocated(locationType,locatorExpression)
    except Exception,e:
        raise e

def waitFrameToBeAvailableAndSwitchToIt(locationType,locatorExprssion,*args):
    """检查frame是否存在,存在则切换进frame控件中"""
    global waitUtil
    try:
        waitUtil.frameToBeAvailableAndSwitchToIt(locationType,locatorExprssion)
    except Exception,e:
        raise e

def waitVisibilityOfElementLocated(locationType,locatorExpression,*args):
    """显式等待页面元素出现在Dom中,并且可见,存在返回该页面元素对象"""
    global waitUtil
    try:
        waitUtil.visibilityOfElementLocated(locationType,locatorExpression)
    except Exception,e:
        raise e

testScript包,存放写入测试结果和执行测试脚本,TestSendMailWithAttachment.py

#encoding=utf-8
from action.PageAction import *
from Util.ParseExcel import ParseExcel
from config.VarConfig import *
import time,traceback
from Util.Log import *

#设置此次测试的环境编码为utf8
import sys
reload(sys)
sys.setdefaultencoding("utf-8")

#创建解析Excel对象
excelObj = ParseExcel()
#将Excel数据文件加载到内存
excelObj.loadWorkbook(dataFilePath)

#用例或用例步骤执行结束后,向excel中写入结果信息
def writeTestResult(sheetObj,rowNo,colNo,testResult,errorInfo = None,picPath = None):
    #测试通过结果信息为绿色,失败为红色
    colorDict = {"pass":"green","fail":"red"}

    #因为“测试用例”工作表和“用例步骤”sheet表中都有测试执行时间和测试结果列,定义此字典是为了区分具体应该写那个工作表
    colsDict = {"testCase":[testCase_runTime,testCase_testResult],"testStep":[testStep_runTime,testStep_testResult]}
    try:
        #在测试步骤sheet中,写入测试时间
        excelObj.writeCellCurrentTime(sheetObj,rowNo = rowNo,colNo = colsDict[colNo][0])
        #在测试步骤sheet中,写入测试结果
        excelObj.writeCell(sheetObj,content = testResult,rowNo = rowNo,colNo = colsDict[colNo][1],style = colorDict[testResult])
        if errorInfo and picPath:
            #在测试步骤sheet中,写入异常信息
            excelObj.writeCell(sheetObj,content = errorInfo,rowNo = rowNo,colNo = testStep_errorInfo)
            #在测试步骤sheet中,写入异常截图
            excelObj.writeCell(sheetObj,content = picPath,rowNo = rowNo,colNo = testStep_errorPic)
        else:
            #在测试步骤sheet中,清空异常信息单元格
            excelObj.writeCell(sheetObj,content="",rowNo = rowNo,colNo = testStep_errorInfo)
            #在测试步骤sheet中,清空异常截图单元格
            excelObj.writeCell(sheetObj,content="",rowNo = rowNo,colNo = testStep_errorPic)
    except Exception,e:
        #在日志文件是写入详细异常堆栈信息
        logging.debug(u"写入excel出错,%s" % traceback.format_exc())

def TestSendMailWithAttachment():
    try:
        #根据excel中的sheet名称获取sheet对象
        caseSheet = excelObj.getSheetByName(u"测试用例")
        #获取测试用例hsheet中是否执行列对象
        isExecuteColumn = excelObj.getColumn(caseSheet,testCase_isExecute)
        #记录执行成功的测试用例个数
        successfulCase = 0
        #记录需要执行的用例个数
        requiredCase = 0
        for idx,i in enumerate(isExecuteColumn[1:]):
            #因为测试用例sheet中第一行为标题,无需执行,所以从第二行开始遍历
            #循环遍历“测试用例”sheet表中的用例, 执行被设置为“执行”的用例
            print i.value
            if i.value.lower() == "y":
                requiredCase += 1
                #获取“测试用例”表中第第idx+2行数据
                caseRow = excelObj.getRow(caseSheet,idx+2)
                #获取第idx+2行的“步骤sheet名”单元格内容
                caseStepSheetName = caseRow[testCase_testStepSheetName - 1].value
                print caseStepSheetName
                #根据用例步骤名获取步骤sheet对象
                stepSheet = excelObj.getSheetByName(caseStepSheetName)
                #获取步骤sheet中步骤数
                stepNum = excelObj.getRowsNumber(stepSheet)
                print stepNum
                #记录测试用例i的步骤执行成功数
                successfulSteps = 0
                logging.info(u"开始执行用例“%s”" % caseRow[testCase_testCaseName - 1].value)
                for step in xrange(2,stepNum + 1):
                    #因为步骤sheet中的第一行为标题行,无需执行,
                    #获取步骤sheet中的step行对象
                    stepRow = excelObj.getRow(stepSheet,step)
                    #获取关键字作为调用 的函数名
                    keyWord = stepRow[testStep_keyWords - 1].value
                    #获取操作元素定位方式作为调用函数的参数
                    locationType = stepRow[testStep_locationType - 1].value
                    #获取操作元素的定位表达式作为调用函数的参数
                    locatorExpression = stepRow[testStep_locatorExpression - 1].value
                    #获取操作值作为调用函数的参数
                    operateValue = stepRow[testStep_operateValue - 1].value
                    #将操作值为数字类型的数据转换成字符串类型,方便字符拼接
                    if isinstance(operateValue,long):
                        operateValue = str(operateValue)

                    print keyWord,locationType,locatorExpression,operateValue

                    expressionStr = ""
                    #构造需要执行的python语句,对应的是PageAction.py文件中的页面动作函数调用的字符串表示
                    if keyWord and operateValue and locationType is None and locatorExpression is None:
                        expressionStr = keyWord.strip() + "(u'" + operateValue + "')"
                    elif keyWord and operateValue is None and locationType is None and locatorExpression is None:
                        expressionStr = keyWord.strip() + "()"
                    elif keyWord and operateValue is None and locationType and locatorExpression:
                        expressionStr = keyWord.strip() + "('" + locationType.strip() + "','" + \
                                        locatorExpression.replace("'",'"').strip() + "',u'" + operateValue + "')"
                    elif keyWord and operateValue is None and locationType and locatorExpression:
                        expressionStr = keyWord.strip() + "('" + locationType.strip() + "','" + \
                                        locatorExpression.replace("'",'"').strip() + "')"
                    print expressionStr

                    try:
                        #通过eval函数,将拼接的页面动作函数调用的字符串表示,当成有效的python表达式执行,从而执行测试步骤sheet中
                        #关键字在PageAction.py文件中对应的映射方法赤完成对页面元素的操作
                        eval(expressionStr)
                        #在测试执行时间列中写入时间
                        excelObj.writeCellCurrentTime(stepSheet,rowNo = step,colNo = testStep_runTime)
                    except Exception,e:
                        #截取异常屏幕图片
                        capturePic = capture_screen()
                        #获取详细的异常堆栈信息
                        errorInfo = traceback.format_exc()
                        #在测试步骤sheet中写入失败信息
                        writeTestResult(stepSheet,step,"caseStep","failed",errorInfo,capturePic)
                        logging.error(u"步骤“%s”执行失败,错误信息:%s" % (stepRow[testStep_testStepDescribe - 1].value,errorInfo))
                    else:
                        #在测试步骤sheet中写入成功信息
                        writeTestResult(stepSheet,step,"caseStep","pass")
                        #每成功一步,successfulSteps变量自增
                        successfulSteps += 1
                        logging.info(u"步骤“%s”执行通过。" % stepRow[testStep_testStepDescribe - 1].value)
                if successfulSteps == stepNum - 1:
                    #当测试用例步骤sheet中所有的步骤都执行成功,方认为此测试用例执行通过,然后将成功信息写入测试用例工作表中,否则写入失败信息
                    writeTestResult(caseSheet,idx + 2,"testCase","pass")
                    successfulCase += 1
                else:
                    writeTestResult(caseSheet,idx + 2,"testCase","Failed")
        logging.info(u"共%d条用例,%d条需要执行,本次执行通过%d条。" % (len(isExecuteColumn)-1,requiredCase,successfulCase))
    except Exception,e:
        #打印详细的异常堆栈信息
        print traceback.print_exc()

在框架目录创建RunTest.py,执行测试脚本:

#encoding=utf-8
from testScripts.TestSendMailWithAttachment import TestSendMailWithAttachment

if __name__ == "__main__":
    TestSendMailWithAttachment()

总结:

完整框架是参考别人的代码写的,最后虽然可以执行成功,但测试结果未成功写入Excel,以后再进行优化

posted @ 2019-07-21 21:35  测试小子  阅读(765)  评论(1编辑  收藏  举报