精华内容
下载资源
问答
  • 关键字驱动测试框架搭建(3)关键字驱动的完整框架:在Pycharm中创建一Python工程,其下再创建Util包,action包,config包,testScripts包,log目录,testData目录,exceptionPictures目录,具体内容如下:Util包中...

    关键字驱动测试框架搭建(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,以后再进行优化

    转载于:https://www.cnblogs.com/test-chen/p/11222872.html

    展开全文
  • 关键字驱动的完整框架: 在Pycharm中创建一Python工程,其下再创建Util包,action包,config包,testScripts包,log目录,testData目录,exceptionPictures目录,具体内容如下: Util包中存放封装的常用函数: ...

    关键字驱动的完整框架:

    在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,以后再进行优化

    软件测试技术交流群:1125760266

    展开全文
  • 一、前言 最近问我自动化的人确实有点多,个人突发奇想:想从0开始讲解python+selenium实现Web...【Selenium篇01】python+selenium实现Web自动化:搭建环境,Selenium原理,定位元素以及浏览器常规操作! https:...

    一、前言

    最近问我自动化的人确实有点多,个人突发奇想:想从0开始讲解python+selenium实现Web自动化测试,请关注博客持续更新!

    这是python+selenium实现Web自动化第八篇博文

    二、Selenium成套博文地址,总有你需要的:

    【Selenium篇01】python+selenium实现Web自动化:搭建环境,Selenium原理,定位元素以及浏览器常规操作!

    https://blog.csdn.net/pengjiangchun/article/details/105532670

    【Selenium02篇】python+selenium实现Web自动化:鼠标操作和键盘操作!

    https://blog.csdn.net/pengjiangchun/article/details/105532867

    【Selenium03篇】python+selenium实现Web自动化:元素三类等待,多窗口切换,警告框处理,下拉框选择

    https://blog.csdn.net/pengjiangchun/article/details/105533107

    【Selenium04篇】python+selenium实现Web自动化:文件上传,Cookie操作,调用 JavaScript,窗口截图

    https://blog.csdn.net/pengjiangchun/article/details/105534081

    【Selenium05篇】python+selenium实现Web自动化:读取ini配置文件,元素封装,代码封装,异常处理,兼容多浏览器执行

    https://blog.csdn.net/pengjiangchun/article/details/105573687

    【Selenium06篇】python+selenium实现Web自动化:日志处理

    https://blog.csdn.net/pengjiangchun/article/details/105574193

    【Selenium07篇】python+selenium实现Web自动化:PO模型,PageObject模式!

    https://blog.csdn.net/pengjiangchun/article/details/105574676

    【Selenium08篇】python+selenium实现Web自动化:数据驱动框架,ddt,关键字驱动框架

    https://blog.csdn.net/pengjiangchun/article/details/105574954

    三、Selenium之-数据驱动框架

    那么问题来了,什么是数据驱动呢?就是,数据的改变从而驱动自动化测试的执行,最终引起测试结果的改变,也就是参数的应用化。

      这里对于数据驱动测试,总结起来就是,数据驱动绝非读取文件(excel、csv、xml)中数据进行参数的赋值测试,因为采用的这种方式的测试,工作重心反而变成了如何读写文件,而对于自动化测试中关心的执行结果统计、断言结果反而不是那么容易去实现。尤其是测试页面结构发生大的调整时,文件类的字段调整获取也要发生较大的修改,所以文件数据驱动测试也是可以的,但是并不是最优解。

      那么什么才是最优的数据驱动测试呢?是的,用单元测试 unittest 结合 ddt 库。使用单元测试可以很方便的解决两个问题:

    (1)断言。利用单元测试的断言机制,我们可以方便的进行预期结果和实际结果的对比;
    (2)数据统计。执行完测试用例后,一共执行了多少条用例,执行成功多少,失败多少,失败的用例错误在哪里?单元测试框架会帮我们统计展示。

    1. DDT 入门

     Python 的 unittest 没有自带数据驱动功能,如果使用 unittest, 同时又想使用数据驱动,就用 DDT 吧。奉上 ddt 官方文档 《DDT 官方文档》。

    DDT 的使用方法:

    (1) ddt.ddt --- 装饰类,也就是继承自 TestCase 的类;
    (2) ddt.data --- 装饰测试方法,参数是一系列的值。
    (3) ddt.file_data --- 装饰测试方法,参数是文件名。文件可以是 json 或 yaml 类型,除.yaml结尾的文件,其他文件均会作为json文件处理。
    (4) ddt.unpack --- 传递的是复杂的数据结构是使用。如:元组或列表。添加到 unpack 上之后,ddt 会自动把元组或者列表对应到多个参数上。
    (5) 测试用例方法名生成规则 --- 

    #!/usr/bin/env python
    # -*- encoding: utf-8 -*-
    """
    @Time    :   2020/4/17
    @Author  :   公众号:软测之家  更多技术干货,软测视频,面试资料请关注!
    @Contact :   软件测试技术群:695458161
    @License :   (C)Copyright 2017-2019, Micro-Circle
    @Desc    :   None
    """
    
    import unittest
    import ddt
    
    @ddt.ddt
    class DDTExample(unittest.TestCase):
        @classmethod
        def setUpClass(cls) -> None:
            print(cls.__name__)
    
        @classmethod
        def tearDownClass(cls) -> None:
            print('...end...')
    
        @ddt.data(
            [1, 2],
            [3, 4],
            [5, 6]
        )
        @ddt.unpack
        def test_add(self, a, b):
            print(a + b)
    
    
    if __name__ == "__main__":
        unittest.main()

    2. 实践应用

     将 ddt 引入到自动化测试中。

    #!/usr/bin/env python
    # -*- encoding: utf-8 -*-
    """
    @Time    :   2020/4/17
    @Author  :   公众号:软测之家  更多技术干货,软测视频,面试资料请关注!
    @Contact :   软件测试技术群:695458161
    @License :   (C)Copyright 2017-2019, Micro-Circle
    @Desc    :   None
    """
    
    import ddt
    from page_object_model.register_business import RegisterBusiness
    from selenium import webdriver
    import unittest
    from time import sleep
    
    @ddt.ddt
    class RegisterDdtCases(unittest.TestCase):
        @classmethod
        def setUpClass(cls) -> None:
            cls.register_url = 'http://www.5itest.cn/register'
            cls.driver = webdriver.Chrome('../tools/chromedriver.exe')
            cls.driver.maximize_window()
            cls.driver.get(cls.register_url)
            sleep(3)
            cls.rb = RegisterBusiness(cls.driver)
    
        @classmethod
        def tearDownClass(cls) -> None:
            sleep(2)
            cls.driver.close()
    
        # 邮箱错误测试的测试用例
        @ddt.data(
            # 顺序分别是:注册邮箱、用户昵称、注册密码、验证码、错误信息定位元素、错误提示信息
            ['123', 'test01', 'test01abc', 'tyu9'],
            ['@163.com', 'test01', 'test01abc', 'tyu9'],
            ['@163', 'test01', 'test01abc', 'tyu9']
        )
        @ddt.unpack
        def test_ddt_email_error(self, register_email, nickname, password, captcha):
            register_email_error = self.rb.register_email_error(register_email, nickname, password, captcha)
            print("register_email_error: ", register_email_error)
            self.assertFalse(register_email_error, '你输入的邮箱错误,但此条测试用例执行成功')
    
    
    if __name__ == "__main__":
        unittest.main()

     

    四、关键字驱动框架

    关键字简单来说就是,把我们的执行操作每一个关键步骤当成一个关键字来对待,用来驱动程序的设计开发。例如:进行web自动化我们的首要是打开浏览器,是的 “打开浏览器” 我们就可以作为一个关键字来对待它,关键字就是来驱动我们程序设计的关键步骤。通过关键字的改变从而驱动自动化测试的执行,最终引起测试结果的改变。

      对于测试一个注册页面,我们来梳理下看有哪些关键词,更深层次了解下关键词模型:

    (1) 打开浏览器 --->  打开浏览器
    (2) 输入注册页面的url --->  输入测试地址
    (3) 页面加载等待 ---> 页面加载等待
    (4) 输入(注册邮箱、用户名、密码、验证码)--->  输入元素
    (5) 点击注册按钮 ---> 点击元素
    (6) 退出浏览器 

    1. 构建关键词类

    #!/usr/bin/env python
    # -*- encoding: utf-8 -*-
    """
    @Time    :   2020/4/17
    @Author  :   公众号:软测之家  更多技术干货,软测视频,面试资料请关注!
    @Contact :   软件测试技术群:695458161
    @License :   (C)Copyright 2017-2019, Micro-Circle
    @Desc    :   None
    """
    
    class RegisterKeyword(object):
        def __init__(self, driver):
            self.fe = FindElement(driver)
    
        # 打开浏览器
        def open_browser(self, browser):
            if browser == 'chrome':
                self.driver = webdriver.Chrome('../tools/chromedriver.exe')
            elif browser == 'firefox':
                self.driver = webdriver.Firefox()
            else:
                self.driver = webdriver.Edge()
    
        # 输入测试地址
        def get_url(self, url):
            self.driver.get(url)
    
        # 定位元素
        def get_element(self, key):
            return self.fe.get_element(key)
    
        # 输入元素
        def send_element_key(self, key, value):
            get_element = self.get_element(key)
            get_element.send_keys(value)
    
        # 点击元素
        def click_element(self, key):
            self.fe.get_element(key).click()
    
        # 页面等待
        @staticmethod
        def wait_loading():
            sleep(3)
    
        # 关闭浏览器
        def close_browser(self):
            self.driver.close()
    
    
    if __name__ == "__main__":
        register_url = 'http://www.5itest.cn/register'
        driver = webdriver.Chrome('../tools/chromedriver.exe')
        driver.get(register_url)
        rk = RegisterKeyword(driver)
        print(rk.get_element('register_email'))
        driver.close()

    2. 关键词模型测试用例

    我们关键词方法直接从 register_keyword 中读取即可,但是测试数据从哪获取到从而传给相应的关键词方法呢?为了方便测试数据方便管理,我们可以将其存储到 Excel中去并获取。

    2.1 读取Excel

    #!/usr/bin/env python
    # -*- encoding: utf-8 -*-
    """
    @Time    :   2020/4/17
    @Author  :   公众号:软测之家  更多技术干货,软测视频,面试资料请关注!
    @Contact :   软件测试技术群:695458161
    @License :   (C)Copyright 2017-2019, Micro-Circle
    @Desc    :   None
    """
    
    import xlrd
    from xlutils.copy import copy
    
    
    class ReadExcel(object):
        def __init__(self, excel_path=None, index=None):
            if excel_path is None:
                self.excel_path = '../data/register_keyword_testdata.xls'
                self.index = 0
            else:
                self.excel_path = excel_path
                self.index = index
    
            # 打开 excel 文件,获取数据列表
            self.data = xlrd.open_workbook(self.excel_path)
            # 读取第一 sheet 页的数据
            self.table = self.data.sheets()[0]
    
        def get_data(self):
            result = []
            rows = self.get_lines()
            if rows != '':
                for i in range(rows):
                    col = self.table.row_values(i)
                    result.append(col)
                return result
            return None
    
        # 获取 excel 行数
        def get_lines(self):
            rows = self.table.nrows
            if rows >= 1:
                return rows
            return None
    
        # 获取单元格的值
        def get_cell(self, row, col):
            if self.get_lines() > row:
                data = self.table.cell(row, col).value
                return data
            return None
    
        def write_data(self, row, col, value):
            read_data = xlrd.open_workbook(self.excel_path)
            write_data = copy(read_data)
            write_data.get_sheet(self.index).write(row, col, value)
            write_data.save("../data/register_keyword_testdata.xls")
            write_data.save(self.excel_path)
    
    
    if __name__ == "__main__":
        re = ReadExcel()
        print(re.get_data())
        print(re.get_lines())
        print(re.get_cell(0, 0))
        re.write_data(11, 0, 123456)

    2.2 测试用例实践

    前面将测试测数据存在到excel中了,接下来怎么写关键字对应的测试用例。

    (1) 拿到操作值,是否执行
    (2) 拿到执行方法
    (3) 拿到输入数据
    (4) 是否有输入数据
            执行方法(输入数据,操作元素)
        没有输入数据
            执行方法(操作元素)
         
    (5) 对比预期结果和实际结果的值
        对比结果一样,测试结论为pass;否则为fail

    #!/usr/bin/env python
    # -*- encoding: utf-8 -*-
    """
    @Time    :   2020/4/17
    @Author  :   公众号:软测之家  更多技术干货,软测视频,面试资料请关注!
    @Contact :   软件测试技术群:695458161
    @License :   (C)Copyright 2017-2019, Micro-Circle
    @Desc    :   None
    """
    
    from util.read_excel import ReadExcel
    from keyword_model.register_keyword import RegisterKeyword
    from selenium import webdriver
    
    class RegisterKeywordCases(object):
        def __init__(self):
            self.rk = RegisterKeyword()
            self.excel_path = '../data/register_keyword_testdata.xls'
    
        # 执行关键字测试方法
        def run_keyword_method(self, keyword_method, operator_element='', send_value=''):
            print('keyword_method ---> ', keyword_method)
            print("operator_element ---> ", operator_element)
            print("send_value ---> ", send_value)
            execute_method = getattr(self.rk, keyword_method)
            print(execute_method)
            if operator_element is '' and send_value is not '':
                result = execute_method(send_value)
            elif operator_element is not '' and send_value is '':
                result = execute_method(operator_element)
            elif operator_element is '' and send_value is '':
                result = execute_method()
            else:
                result = execute_method(operator_element, send_value)
            return result
    
        # 执行关键词测试用例
        def run_keyword_excel_cases(self):
            handle_excel = ReadExcel(self.excel_path)
    
            # 获取 excel 关键词测试用例的条数
            cases_numbers = handle_excel.get_lines()
            print("注册页获取到的关键词测试的测试用例条数为:%s" % cases_numbers)
    
            # 循环遍历测试用例
            if cases_numbers:
                # 第 0 行是标题行不作为用例执行
                for i in range(1, cases_numbers):
                    # 获取测试用例的名称
                    testcase_name = handle_excel.get_cell(i, 0)
                    # 获取用例是否执行
                    is_run = handle_excel.get_cell(i, 1)
                    if is_run == 'yes':
                        keyword_method = handle_excel.get_cell(i, 2)
                        operator_element = handle_excel.get_cell(i, 3)
                        send_value = handle_excel.get_cell(i, 4)
                        except_result = handle_excel.get_cell(i, 5)
                        actual_result = handle_excel.get_cell(i, 6)
    
                        # 反射
                        self.run_keyword_method(keyword_method, operator_element, send_value)
    
                        # if except_result is not '':
                        #     except_value = self.run_keyword_method(keyword_method)
                    else:
                        print('第 %s 条用例不执行,用例名称是: [%s],无预期结果' % (i, testcase_name))
            else:
                print("略略略~,请检查你是否有写测试用例!")
    
    
    if __name__ == "__main__":
        rkc = RegisterKeywordCases()
        # rkc.run_keyword_method('open_browser', '', 'chrome')
        # rkc.run_keyword_method('get_url', '', 'http://www.5itest.cn/register')
        rkc.run_keyword_excel_cases()

    五、行为驱动模型

    什么是行为驱动测试呢?行为驱动(Behave Driven Development)测试,是一种敏捷的开发方法,通常应用在自动化测试中,通过使用自然描述语言确定自动化脚本。不喜欢这种方式用在自动化脚本里。

    六、持续更新中请关注

    如果你觉得此文对你有帮助,如果你对软件测试、接口测试、自动化测试、面试经验交流感兴趣欢迎加入:

    软件试技术群:695458161,群里发放的免费资料都是笔者十多年测试生涯的精华。还有同行大神一起交流技术哦。

    作者:诸葛
    出处:https://blog.csdn.net/pengjiangchun
    原创不易,欢迎转载,但未经作者同意请保留此段声明,并在文章页面明显位置给出原文链接。

    展开全文
  • 1、基于关键字驱动+数据驱动形式实现的测试框架; 2、基于POM+数据驱动实现的测试框架 语言:python 自动化测试模块:selenium、appium、Requests 设计模式:关键字驱动、POM 数据模块:Excel、Yaml、text、xmind、...
    • 概念

      基于所有技术来综合实现的一个结构体叫做框架

    • 框架类型

      测试框架有且仅有两种类型
      • 基于关键字驱动+数据驱动实现的测试框架
      • 基于POM+数据驱动实现的测试框架
    • 语言

      python

    • 自动化测试模块

      selenium、appium、Requests

    • 设计模式

      关键字驱动、POM

    • 数据模块

      Excel、Yaml、text、xmind、CSV……

    • 配置模块

      项目路径、报告、用例等各类配置项

    • 日志

      logging+trackback

    • 用例管理

      UnitTest、Pytest

    • 数据驱动

      ddt、openpyxl、os、open

    • 测试报告

      HTMLTestRunner、Allure

    • 邮件

      SMTP

    • 持续集成

      Jenkins

    • 测试框架效率

      多线程任务并发与分布式集群管理

    展开全文
  • 测试流程,从手工转换为自动化实现形式 目前主流的自动化实现。基于selenium+webdriver来实现的...现阶段, 测试框架的核心内容一定是关键字驱动的: 1、解决代码冗余 2、解决可读性 3、解决维护性 4、解决代码的复用性
  • (1)关键字驱动 (2)不用写代码就可以实现自动化测试 (3)支持数据驱动的测试用例 (4)HTML格式的测试结果,方便阅读 (5)易于管理,方便集成,扩展性强等 本机已安装python36 1、安装RF组件 打开cmd依次输入...
  • Robot Framework是主流的关键字驱动测试框架之一。 关键字模型设计 目标:实现一个百度搜索的关键字模型自动化测试脚本。 搭建步骤: 新建三个Python Package,并分别创建3个py文件: config包,创建data.xls...
  • python3.6+robotFramework环境搭建(全)

    千次阅读 2020-09-28 11:28:51
    它具备良好的可扩展性,支持关键字驱动,可以同时测试多种类型的客户端或者接口,可以进行分布式测试执行。主要用于轮次很多的验收测试和验收测试驱动开发(ATDD)。 在我们进行全球化测试的时候可以用此框架来编写...
  • 它使用关键字驱动的测试方法,利用已有的关键字,测试人员可以创建自己需要的关键字形成更高级的行为。详细说明可以去百度搜一搜。 Robot Framework环境搭建 PythonPython3.6.7 RF框架是基于Python的,所以...
  • 它具有易于使用的表格测试数据语法,它采用了关键字驱动的测试方法。其检测能力可以通过测试库实现Python或Java扩展,用户可以使用相同的语法,用于创建测试用例的创建新的更高层次的关键词。 RIDE 是一
  • RF 框架的优点在于对编程新手比较友好,支持关键字驱动。 RF 框架通常的适用场景是用一位有编程功力的自动化工程师搭建框架,封装好常用的关键字,然后由不同的功能业务部门的测试人员调用关键字进行自动化测试...
  • 关键字驱动。用已有关键字形成业务关键字 测试用例支持变量使用、IF语句和FOR循环 支持继承svn、git、jenkins等工具 灵活、可拓展 丰富的编辑工具 环境准备: RF框架运行环境:Python2/3 Python库:...
  • 项目分为九部分:基础项目实战丶PageObject丶Unittest丶数据驱动丶关键字驱动丶行为驱动丶日志模块丶持续继承丶源码管理 实战基础:[{"Selenium3":["环境搭建","基础API使用"]},"如何破解验证...
  • Robot Framework是一个基于Python可扩展地关键字驱动的测试自动化框架,使用Apache License 2.0,由Robot Framework Foundation开发和赞助。 Robot Framework被广泛地使用在端到端地验收测试以及ATDD(acceptance-...
  • RobotFramework 介绍Robot Framework是一个基于Python可扩展地关键字驱动的测试自动化框架,使用Apache License 2.0,由Robot Framework Foundation开发和赞助。Robot Framework被广泛地使用在端到端地验收测试以及...
  • 具备良好的可扩展性,支持关键字驱动,可以同时测试多种类型的客户端或者接口,可以进行分布式测试执行。主要用于轮次很多的验收测试和验收测试驱动开发(ATDD)。正文: 1.环境搭建 1.1 robotframework安装:pip ...
  • (提示:我的安装版本是robotFramework3.0+ride1.5+python2.7+wxpython2.8,至于... robotFramework是一个通用的自动化测试框架来进行验收测试和验收测试驱动开发模式,它具有易于使用的表格的测试数据和关键字测试驱...
  • 它具备良好的可扩展性,支持关键字驱动,可以同时测试多种类型的客户端或者接口,可以进行分布式测试执行。主要用于轮次很多的验收测试和验收测试驱动开发(ATDD)。  在我们进行全球化测试的时候可以用此框架来...
  • Robot Framework是一款优秀的关键字驱动测试框架,基于Python开发,要想使用Robot Framework,首先需要有Python环境,接下来,笔者以python2(虽然现在可以在python2和python3共存的环境中搭建,但是笔者真心不建议这么做)...
  • 它具备良好的可扩展性,支持关键字驱动,可以同时测试多种类型的客户端或者接口,可以进行分布式测试执行。主要用于轮次很多的验收测试和验收测试驱动开发(ATDD) 关键字驱动 在这里需要首先介绍下RF(Robot ...
  • Robot Framework是一款python编写的功能自动化测试框架。具备良好的可扩展性,支持关键字驱动,可以同时测试多种类型的客户端或者接口,可以进行分布式测试执行。 Robot Framework特点: 1.开源的,不解释 2.基于...
  • Robot Framework/RIDE 环境搭建

    千次阅读 2016-09-09 11:13:33
    RobotFramework是一种基于Python的可扩展关键字驱动自动化测试框架。通常用于端到端的可接收测试和可接收测试驱动的开发,可以用于测试声明涉及到多种技术和接口的分布式的,异构的应用系统。 RIDE是 RF框架原生的...
  • 它具有易于使用的表格测试数据语法,并利用关键字驱动的测试方法。它的测试功能可以通过使用Python或Java实现的测试库进行扩展,并且用户可以使用与创建测试用例相同的语法从现有的关键字创建新的高级关键字 Python...
  • Robot Framework环境搭建

    2019-10-04 22:32:46
    具备良好的可扩展性,支持关键字驱动,可以同时测试多种类型的客户端或者接口,可以进行分布式测试执行。主要用于轮次很多的验收测试和验收测试驱动开发(ATDD)。【百度百科详情】 环境搭建 Robot...
  • 先学习自动化测试基础,学习Appium操作,元素定位、操作、等待、滑动等,深入讲解PO、unittest、yaml、配置文件、测试报告等知识,基于关键字驱动、Pytest和jenkins持续集成完成App测试框架设计与开发。 Python自动...
  • robot framework环境搭建

    2018-04-12 14:51:00
    具备良好的可扩展性,支持关键字驱动,可以同时测试多种类型的客户端或者接口,可以进行分布式测试执行。主要用于轮次很多的验收测试和验收测试驱动开发(ATDD)。 环境支持: 1.robotframework框架 2....
  • Robot Framework是一款python编写的功能自动化测试...具备良好的可扩展性,支持关键字驱动,可以同时测试多种类型的客户端或者接口,可以进行分布式测试执行。主要用于轮次很多的验收测试和验收测试驱动开发(ATDD)

空空如也

空空如也

1 2 3 4
收藏数 71
精华内容 28
关键字:

python关键字驱动框架搭建

python 订阅