python自动化之UI自动化框架搭建三(关键字驱动)

十二、util中新建一个ParseExcel.py,用于实现读取Excel数据文件代码封装

# ending-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)  # 设置字体颜色
        # 颜色对应的RGB值
        self.RGBDict = {'red': 'FFFF3030', 'green': 'FF008B00'}

    # 将Excel文件加载到内存, 并获取期workbook对象
    def loadWordBook(self, excelPathAndName):

        try:
            self.workbook = openpyxl.load_workbook(excelPathAndName)

        except Exception as e:
            raise e

        self.excelFile = excelPathAndName
        return self.workbook

    # 根据sheet名获取该sheet对象
    def getSheetByName(self, sheetName):

        try:
            sheet = self.workbook[sheetName]
            return sheet
        except Exception as e:
            raise e

    # 根据sheet索引号获取该sheet对象
    def getSheetByIndex(self, sheetIndex):

        try:
            sheet = self.workbook.worksheets[0]
            return sheet
        except Exception as e:
            raise e

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

        return sheet.max_row

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

        return sheet.max_column

    # 获取sheet中有数据区域的开始的行号
    def getStartRowsNumber(self, sheet):

        return sheet.min_row

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

        return sheet.min_column

    # 获取sheet中某一行,返回这一行所有数据内容组成的tuple
    # 下标从1开始,sheet.rows[1]表示第一行
    def get_row_value(self, sheet, row, max_col):

        try:
            # return sheet.rows[rowNo-1]  # 最新版本sheet.rows 返回的为一个生成器,所以不能采用此方法
            row_data = []
            for num in range(1, max_col+1):
                cell_value = sheet.cell(row=row, column=num).value
                row_data.append(cell_value)
            return row_data

        except Exception as e:
            raise e

    # 获取sheet中某一列,返回这一列所有数据组成的tuple
    # 下标从1开始,sheet.columns[1]表示第一列
    def get_col_value(self, sheet, row, col):

        try:
            col_data = []
            for num in range(1, row+1):
                cell_value = sheet.cell(row=num, column=col).value
                col_data.append(cell_value)
            return col_data

        except Exception as e:
            raise e

    # 获取某个单元格的值
    def get_cell_value(self, sheet, row, col):
        try:
            cell_value = sheet.cell(row=row, column=col).value
            return cell_value
        except Exception as e:
            raise e

    # 获取某个单元的对象,可以根据单元格所在位置的数字索引,也可以根据Excel中单元格的编码及坐标
    def getCellOfObject(self, sheet, coordinate=None, rowNo=None, colNo=None):

        if coordinate is not None:
            try:
                return sheet.cell(coordinate=coordinate)
            except Exception as e:
                raise e
        elif coordinate is None and rowNo is not None and colNo is not None:
            try:
                return sheet.cell(row=rowNo, column=colNo)
            except Exception as e:
                raise e
        else:
            raise Exception('Insufficient Coordinates of cell!')

    # 根据单元格在Excel中的编码坐标或者数字索引坐标向单元格中写入数据,参数style表示颜色
    def writeCell(self, sheet, content, coordinate=None, rowNo=None,
                  colNo=None, style=None):
        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 as e:
                raise e

        elif coordinate is 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(row=rowNo, column=colNo).font = \
                        Font(color=self.RGBDict[style])

                self.workbook.save(self.excelFile)
            except Exception as e:
                raise e

        else:
            raise Exception('Insufficient Coordinates of cell!')

    # 写入当前的时间,下标从1开始
    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 is not None:
            try:
                sheet.cell(coordinate=coordinate).value=currentTime
                self.workbook.save(self.excelFile)
            except Exception as e:
                raise e
        elif coordinate is 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 as e:
                raise e
        else:
            raise Exception('Insufficient Coordinates of cell!')


if __name__ == '__main__':

    pe = ParseExcel()
    # 测试使用的Excel文件
    pe.loadWordBook('******.xlsx')
    print("通过名称获取sheet对象的名字:%s" % pe.getSheetByName("测试").title)
    print("通过index序号获取sheet对象的名字:%s" % pe.getSheetByIndex(0).title)

    sheet = pe.getSheetByIndex(0)
    print(type(sheet))

    maxRow = pe.getRowsNumber(sheet)  # 获取最大行号
    maxCol = pe.getColsNumber(sheet)  # 获取最大列号


    rows = pe.get_row_value(sheet, 3, maxCol)  # 获取某一行内容
    print(rows)
    cols = pe.get_col_value(sheet, 1, maxRow)   # 获取某一列内容

    pe.writeCell(sheet, '测试用', rowNo=26, colNo=1)
    pe.writeCellCurrentTime(sheet, rowNo=26, colNo=2)

 

十三、在testData目录中新建一个楼宇测试.xlsx的Excel文件,并在此Excel文件中新建三个工作表(根据实际测试用例情况添加),分别命名为"测试用例"、"登录"、"新建"

测试用例:

 

 

登录:

 

 

新建:

 

说明:

  登录 和 新建工作表中关键字列内容对应 action包中 PageAction.py文件中的函数名;“操作元素定位方式”列表示定位元素所使用的定位方式;“表达式”列表示元素定位方式对应表达式;“操作值”列,表示需要输入的内容 

 

十四、修改config包中的VarConfig.py文件

# encoding=utf-8

import os

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

# 异常截图存放目录绝对路径
screenPicturesDir = parenthDirPath + "/exceptionpictures"

# 测试数据文件存放绝对路径
dataFilePath = parenthDirPath + "/testData/楼宇测试"

# 测试数据文件中,测试用例表中部分列对应的数字序号
testCase_testCaseName = 2
testCase_testStepSheetName = 4
testCase_testisExecute = 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

 

十五、修改testScripts包中的TestCreatBuilding.py文件

# encoding=utf-8
from KeyWordsFrameWork.action.PageAction import *
from KeyWordsFrameWork.util.ParseExcel import ParseExcel
from KeyWordsFrameWork.config.VarConfgi import *
import time
import traceback

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


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

    # 因为测试用例工作表和用例步骤sheet表中都有测试执行时间和测试结果列,
    # 定义此字典对象是为了区分具体应该写哪个工作表
    colsDict = {
        "testCase": [testCase_runTime, testCase_testResult],
        "caseStep": [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:
        print("写Excel出错,%s" % traceback.print_exc())


def TestCreatBuild():

    try:
        # 根据Excel文件中的sheet名称获取sheet对象
        caseSheet = excelObj.getSheetByName("测试用例")
        # 获取测试用例sheet中是否执行列对象
        maxRow = excelObj.getRowsNumber(caseSheet)  # 获取最大行号
        maxCol = excelObj.getColsNumber(caseSheet)  # 获取最大列号
        isExecuteCol = excelObj.getColumn(caseSheet, maxRow, testCase_testisExecute)
        # print(isExecuteCol)

        # 记录执行成功的测试用例个数
        successfulCase = 0

        # 记录需要执行的测试用例个数
        requiredCase = 0

        for idx, i in enumerate(isExecuteCol[1:]):
            # 因为用例sheet中第一行为标题行,无需执行
            # 循环遍历测试用例表中的测试用例,执行被设置为执行的用例
            if i.lower() == "y":
                requiredCase += 1
                # 获取测试用例中第idx+2行数据
                caseRow = excelObj.getRow(caseSheet, idx+2, maxCol)
                # 获取第idx+2行的步骤sheet单元格内容
                caseStepName = caseRow[testCase_testStepSheetName-1]

                # 根据用例步骤名获取步骤sheet对象
                stepSheet = excelObj.getSheetByName(caseStepName)
                # 获取步骤sheet中的步骤数
                stepNum = excelObj.getRowsNumber(stepSheet)
                # 获取最大行数和列数
                maxstepRow = excelObj.getRowsNumber(caseSheet)  # 获取最大行号
                maxstepCol = excelObj.getColsNumber(caseSheet)  # 获取最大列号
                # 记录用例i的步骤成功数
                successfulSteps = 0
                print("开始执行用例 %s" % caseStepName)

                for step in range(2, stepNum+1):
                    # 获取步骤sheet中第step行内容
                    stepRow = excelObj.getRow(stepSheet, step, maxstepCol)

                    # 获取关键字作为调用的函数名
                    keyWord = stepRow[testStep_keyWords-1]

                    # 获取操作元素定位方式作为调用的函数的参数
                    locationType = stepRow[testStep_locationType-1]

                    # 获取操作元素的定位表达式作为调用函数的参数
                    locatorExpression = stepRow[testStep_locatorExpression-1]

                    # 获取操作值作为调用函数的参数
                    operateValue = stepRow[testStep_operateValue-1]

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

                    elif keyWord and operateValue is None and locationType is None\
                            and locatorExpression is None:
                        expressionStr = keyWord.strip() + '()'

                    elif keyWord and locationType and locatorExpression \
                            and operateValue:
                        expressionStr = keyWord.strip() + '("' + locationType.strip() \
                                        + '","' + locatorExpression.strip() + '","' \
                                        + str(operateValue) + '")'

                    elif keyWord and locationType and locatorExpression \
                            and operateValue is None:
                        expressionStr = keyWord.strip() + '("' + locationType.strip() \
                                        + '","' + locatorExpression.strip() + '")'

                    try:
                        # 通过eval函数,将拼接的页面动作函数调用的字符串表示当成有效的python表达式执行,
                        # 从而执行测试步骤的sheet中关键字在PageAction.py文件中对应的映射方法
                        # 完成对页面元素的操作
                        eval(expressionStr)

                        # 测试执行时间列写入执行时间
                        excelObj.writeCellCurrentTime(
                            stepSheet, rowNo=step, colNo=testStep_runTime
                        )

                    except Exception as e:
                        # 截取异常屏幕图片
                        capturePic = capture_screen()

                        # 获取详细的异常信息
                        errorInfo = traceback.format_exc()
                        # 测试步骤sheet中写入失败信息
                        writeTestResult(
                            stepSheet, step, "caseStep", "fail", errorInfo, capturePic
                        )
                        print("步骤%s执行失败" % stepRow[testStep_testStepDescribe-1])

                    else:
                        # 在测试步骤sheet中写入成功信息
                        writeTestResult(stepSheet, step, "caseStep", "pass")

                        # 每成功一步,successfulSteps变量+1
                        successfulSteps += 1
                        print(("步骤 %s 执行成功" % stepRow[testStep_testStepDescribe-1]))

                if successfulSteps == stepNum - 1:

                    # 当测试用例步骤sheet中所有的步骤都执行成功,方认为此测试用例执行
                    # 通过,然后将成功信息写入测试用例工作表中,否则写入失败信息
                    writeTestResult(caseSheet, idx+2, "testCase", "pass")
                    successfulCase += 1
                else:
                    writeTestResult(caseSheet, idx+2, "testCase", "fail")

        print("共%d条测试用,%d条需要被执行,本次执行通过%d条。" % (len(isExecuteCol)-1,
                                               requiredCase, successfulCase))
    except Exception as e:
        print(traceback.print_exc())


if __name__ == "__main__":
    TestCreatBuild()

 

posted @ 2021-10-05 22:13  鹄望  阅读(381)  评论(0编辑  收藏  举报