def assert_string_in_pagesource(self, assertString): # 断言页面源码是否存在某关键字或关键字字符串 try: assert assertString in self.driver.page_source, "%s not found in page source!" % assertString logger.info("查找预期结果成功,%s" % assertString) except AssertionError as e: raise AssertionError(e) except Exception as e: raise e
def assert_result(respons, key_word): """验证数据的正确性""" try: assert key_word in respons.text #print("断言成功") logger.info("断言成功") return True except AssertionError as e: #print("断言失败") logger.info("断言失败") return False
def get_test_case_sheet_names(test_data_excel_path): #读取行号和需要执行的测试用例sheet名称 test_cases_wb = Excel(test_data_excel_path) test_cases_wb.get_sheet_by_index(1) test_case_to_run_sheet_names = [] for row in test_cases_wb.get_all_row_values(): #1个需要和1个测试用例sheet名称组成一个元祖 #多个元祖放入列表中,组成一个测试用例sheet的集合列表 if row[test_case_test_step_sheet_name_col_no] and row[ test_case_is_executed_dol_no].lower() == 'y': test_case_to_run_sheet_names.append( (row[test_case_row_no_col_no], row[test_case_test_step_sheet_name_col_no])) #print("test_case_to_run_sheet_names: %s" % test_case_to_run_sheet_names) logger.info("test_case_to_run_sheet_names: %s" % test_case_to_run_sheet_names) return test_case_to_run_sheet_names
def find_element(self, selctor): """ 这个地方为什么根据=>来切割字符串,请看页面里定位元素的方法 如果采用等号,结果很多xpath表达式中包含一个=,这样会造成切割不准确,影响元素定位 :param selctor: :return: """ element = '' if '=>' not in selctor: return self.driver.find_element_by_id(selctor) selctor_by = selctor.split('=>')[0] selctor_value = selctor.split('=>')[1] if selctor_by == "i" or selctor_by == "id": try: element = self.driver.find_element_by_id(selctor_value) logger.info("找到了元素 %s 成功" "%s 该值为: %s" % (element.text, selctor_by, selctor_value)) except NoSuchElementException as e: logger.error("NoSuchElementException: %s" % e) elif selctor_by == "n" or selctor_by == "name": element = self.driver.find_element_by_name(selctor_value) elif selctor_by == "class" or selctor_by == "class_name": element = self.driver.find_element_by_class_name(selctor_value) elif selctor_by == "link" or selctor_by == "link_text": element = self.driver.find_element_by_link_text(selctor_value) elif selctor_by == "partial" or selctor_by == "partial_link_text": element = self.driver.find_element_by_partial_link_text( selctor_value) elif selctor_by == "tag" or selctor_by == "tag_name": element = self.driver.find_element_by_tag_name(selctor_value) elif selctor_by == "x" or selctor_by == "xpath": try: element = self.driver.find_element_by_xpath(selctor_value) logger.info("找到了元素 %s 成功" "%s 该值为: %s" % (element.text, selctor_by, selctor_value)) except NoSuchElementException as e: logger.error("NoSuchElementException:%s" % e) elif selctor_by == "s" or selctor_by == "selector_selector": element = self.driver.find_element_by_css_selector(selctor_value) else: raise NameError("请输入有效的定位元素类型") return element
def parse_get_media_su(data): serial_num = data[2:4] peripheral = data[6:7] media_type = data[8:9] media_id = data[9:13] pkg_total = data[13:15] pkg_num = data[15:17] if byte2str(pkg_total) == '0000' and byte2str(pkg_num) == '0000': if byte2str(media_type) == '02': logger.info('—————— 告警视频未录制完 {} ——————'.format( byte2str(data))) query_media_body = '%s%s%s%s%s' % ( COMPANY_NO, byte2str(peripheral), '50', byte2str(media_type), byte2str(media_id)) query_media = '%s%s%s%s%s' % ( SU_FLAG, calc_check_code(query_media_body), num2big( GlobalVar.get_serial_no()), query_media_body, SU_FLAG) query_msg_queue.put(query_media) send_queue.put(query_msg_queue.get(block=False)) elif byte2str(media_type) == '00': logger.error('—————— 告警数据不存在 {} ——————'.format( byte2str(data))) else: return_state = '00' img_return_body = '%s%s%s%s%s%s%s%s' % ( COMPANY_NO, byte2str(peripheral), '51', byte2str(media_type), byte2str(media_id), byte2str(pkg_total), byte2str(pkg_num), return_state) img_return = '%s%s%s%s%s' % ( SU_FLAG, calc_check_code(img_return_body), byte2str(serial_num), img_return_body, SU_FLAG) send_queue.put(img_return) media_queue.put(data) total_pkg = int(byte2str(data[13:15]), 16) rec_pkg = int(byte2str(data[15:17]), 16) if rec_pkg == total_pkg - 1: try: send_queue.put(query_msg_queue.get(block=False)) except queue.Empty: global fetch_media_flag fetch_media_flag = True
def get_unique_number_value(unique_number): global global_vars try: with open(data_file, "rb") as fp: var = pickle.load( fp ) # 读取pickle序列化字节流文件中内容,反序列化成python的字典对象:{"unique_num1":100,"unique_num2":1000} data = var[unique_number] # 获取字典对象中key为unique_number的值 #print("全局唯一数当前生成的值是:%s" %data) logger.info("全局唯一数当前生成的值是:%s" % data) global_vars[unique_number] = str(data) var[unique_number] += 1 # 把字典对象中key为unique_number的值进行加一操作,以便下提取时保持唯一 with open(data_file, "wb") as fp: pickle.dump(var, fp) # 修改后的字典对象,序列化到字节流文件中 except Exception as e: #print("获取测试框架的全局唯一数变量值失败,请求的全局唯一数变量是%s,异常原因如下:%s" %(unique_number,e)) logger.debug(e) data = None finally: return data
def appRank(): driver = webdriver.Remote('http://localhost:4723/wd/hub', getDesiredcaps()) try: excelObj = ParseExcel() excelObj.loadWorkBook(dataFilePath) appRankSheet = excelObj.getSheetByName("应用") isExecute = excelObj.getColumn(appRankSheet, app_isExecute) appRankStringCols = excelObj.getColumn(appRankSheet, app_assertKeyWord) for idx, i in enumerate(isExecute[1:]): appRankString = appRankStringCols[idx + 1].value logger.info("----------应用排行“{}”开始执行".format(appRankString)) if i.value == 'y': try: AppRankAction.appRank(driver, appRankString) except Exception as e: excelObj.writeCellCurrentTime(appRankSheet, rowNo=idx + 2, colsNo=app_runTime, style="red") excelObj.writeCell(appRankSheet, "Faild", rowNo=idx + 2, colsNo=app_testResult, style="red") logger.error( "在“应用”模块,断言排列前三的APP“{}”失败\n异常信息:{}".format(appRankString, traceback.format_exc())) else: excelObj.writeCellCurrentTime(appRankSheet, rowNo=idx + 2, colsNo=app_runTime, style="green") excelObj.writeCell(appRankSheet, "Pass", rowNo=idx + 2, colsNo=app_testResult, style="green") logger.info("在“应用”模块,断言排列前三的APP“{}”成功".format(appRankString)) else: excelObj.writeCell(appRankSheet, "", rowNo=idx + 2, colsNo=app_runTime, ) excelObj.writeCell(appRankSheet, "", rowNo=idx + 2, colsNo=app_testResult) logger.info("排列前三的用例“{}”被忽略执行".format(appRankString)) except Exception as e: logger.error("数据驱动框架主程序发生异常\n异常信息:{}".format(traceback.format_exc())) finally: driver.quit()
def searchApp(): driver = webdriver.Remote('http://localhost:4723/wd/hub', getDesiredcaps()) try: excelObj = ParseExcel() excelObj.loadWorkBook(dataFilePath) searchSheet = excelObj.getSheetByName("搜索") isExecute = excelObj.getColumn(searchSheet, search_isExecute) searchKeyWordCols = excelObj.getColumn(searchSheet, search_searchKeyWord) for idx, i in enumerate(isExecute[1:]): searchKeyWord = searchKeyWordCols[idx + 1].value logger.info("----------搜索APP“{}”开始执行".format(searchKeyWord)) if i.value == 'y': searchRow = excelObj.getRow(searchSheet, idx + 2) assertKeyWord = searchRow[search_assertKeyWord - 1].value try: SearchAction.search(driver, searchKeyWord, assertKeyWord) except Exception as e: excelObj.writeCellCurrentTime(searchSheet, rowNo=idx + 2, colsNo=search_runTime, style="red") excelObj.writeCell(searchSheet, "Faild", rowNo=idx + 2, colsNo=search_testResult, style="red") logger.error("搜索APP“{}”失败\n异常信息:{}".format( searchKeyWord, traceback.format_exc())) else: excelObj.writeCellCurrentTime(searchSheet, rowNo=idx + 2, colsNo=search_runTime, style="green") excelObj.writeCell(searchSheet, "Pass", rowNo=idx + 2, colsNo=search_testResult, style="green") logger.info("搜索APP“{}”成功".format(searchKeyWord)) else: excelObj.writeCell( searchSheet, "", rowNo=idx + 2, colsNo=search_runTime, ) excelObj.writeCell(searchSheet, "", rowNo=idx + 2, colsNo=search_testResult) logger.info("搜索APP“{}”的用例被忽略执行".format(searchKeyWord)) except Exception as e: logger.error("数据驱动框架主程序发生异常\n异常信息:{}" % (traceback.format_exc())) finally: driver.quit()
def send_mail(attach_file_path): mail_host = ProjConfigVar.mail_host mail_user = ProjConfigVar.mail_user mail_pass = ProjConfigVar.mail_pass sender = ProjConfigVar.sender receivers = ProjConfigVar.receivers #创建一个带附件类型的MIMEMultipart()实例 message = MIMEMultipart() #对邮件属性赋值 message['From'] = formataddr(['李国芳', '*****@*****.**']) message['To'] = ''.join(receivers) subject = '接口自动化执行测试报告' message['Subject'] = Header(subject, 'utf-8') #邮件正文内容 message.attach(MIMEText('最新执行的接口自动化测试报告,请参阅附件内容!', 'plain', 'utf-8')) #构造附件1,传送测试结果的exce文件 #print("os.path.exists(attach_file_path):%s" % os.path.exists(attach_file_path)) logger.info("os.path.exists(attach_file_path):%s" % os.path.exists(attach_file_path)) logger.info(os.path.exists(attach_file_path)) #构建附件对象,添加html文件 att = MIMEBase('application', 'octet-stream') att.set_payload(open(attach_file_path, 'rb').read()) att.add_header('Content-Disposition', 'attachment', filename=('utf-8', '', '接口自动化测试报告.html')) encoders.encode_base64(att) message.attach(att) try: #创建一个SMTP对象 smtpObj = smtplib.SMTP(mail_host) #传入用户名和密码登录邮箱 smtpObj.login(mail_user, mail_pass) #发送传参数包括发件人地址,收件人地址和邮件内容 smtpObj.sendmail(sender, receivers, message.as_string()) #print("邮件发送成功") logger.info("邮件发送成功") except smtplib.SMTPException as e: #print("Error:无法发送邮件",e) logger.debug(e)
def test_cases_from_test_data_sheet(test_data_excel_path, test_data_sheet_name): #print(test_data_excel_path) logger.info(test_data_excel_path) test_cases_wb = Excel(test_data_excel_path) test_cases_wb.get_sheet_by_name(test_data_sheet_name) #print("设定的测试用例sheet名称是:%s" % test_data_sheet_name) logger.info("设定的测试用例sheet名称是:%s" % test_data_sheet_name) #读取所有的接口测试用例 #print("test_cases_wb_row_values():%s" % test_cases_wb.get_all_row_values()) logger.info("test_cases_wb_row_values():%s" % test_cases_wb.get_all_row_values()) #print("*"*50) test_cases = [] for row in test_cases_wb.get_all_row_values(): if row[test_data_is_executed_col_no] and row[ test_data_is_executed_col_no].lower() == "y": test_case = row[test_data_row_no_col_no],row[test_data_interface_name_col_no],row[test_data_request_data_col_no],\ row[test_data_assert_word_col_no],row[test_data_correlate_regx_col_no] test_cases.append(test_case) #print("test_cases:",test_cases) logger.info("test_cases:%s" % test_cases) return test_cases
def appstore(): try: excelObj = ParseExcel() excelObj.loadWorkBook(dataFilePath) caseSheet = excelObj.getSheetByName("测试用例") caseNameCols = excelObj.getColumn(caseSheet, testCase_testCaseName) isExecuteCaseCols = excelObj.getColumn(caseSheet, testCase_isExecute) # 记录需要执行的用例个数 requiredCaseNum = 0 # 记录执行成功的用例个数 successfulCaseNum = 0 for idx, i in enumerate(isExecuteCaseCols[1:]): # 测试用例sheet中第一行为标题,无须执行 if i.value == "y": requiredCaseNum += 1 caseRow = excelObj.getRow(caseSheet, idx + 2) caseName = caseNameCols[idx + 1].value stepSheetName = caseRow[testCase_testStepSheetName - 1].value # 根据用例的sheet名获取用例的sheet对象 stepSheet = excelObj.getSheetByName(stepSheetName) # 记录用例步骤的个数 stepNum = excelObj.getRowsNumber(stepSheet) # 记录用例步骤执行成功的个数 successfulStepNum = 0 logger.info("----------" + caseName) for j in range(2, stepNum + 1): # 用例步骤中的第一行为标题,无须执行 stepRow = excelObj.getRow(stepSheet, j) # 获取用例步骤中描述 StepDescription = stepRow[caseStep_caseStepDescription - 1].value # 获取函数名 keyWord = stepRow[caseStep_keyWord - 1].value # 获取操作元素的定位方式 locationType = stepRow[caseStep_locationType - 1].value # 获取操作元素定位方式的表达式 locatorExpression = stepRow[caseStep_locatorExpression - 1].value # 获取函数中的参数 operatorValue = stepRow[caseStep_operatorValue - 1].value # 数值类数据从excel取出后为int型数据,转换为字符串,方便拼接 if isinstance(operatorValue, int): operatorValue = str(operatorValue) if keyWord and locationType and locatorExpression and operatorValue: step = keyWord + "('{}','{}','{}')".format( locationType, locatorExpression, operatorValue) elif keyWord and locationType and locatorExpression: step = keyWord + "('{}','{}')".format( locationType, locatorExpression) elif keyWord and operatorValue: step = keyWord + "('{}')".format(operatorValue) else: step = keyWord + "()" try: # 用例步骤执行执行成功,写入执行结果和日志 eval(step) successfulStepNum += 1 writeResult(excelObj, stepSheet, "Pass", j, "caseStep") logger.info("执行步骤“{}”成功".format(StepDescription)) except Exception as e: # 用例步骤执行执行成功 errPicPath = capture_screen() errMsg = traceback.format_exc() writeResult(excelObj, stepSheet, "Faild", j, "caseStep", errMsg=errMsg, errPicPath=errPicPath) logger.error("执行步骤“{}”失败\n异常信息:{}".format( StepDescription, traceback.format_exc())) if successfulStepNum == stepNum - 1: successfulCaseNum += 1 writeResult(excelObj, caseSheet, "Pass", idx + 2, "testCase") else: writeResult(excelObj, caseSheet, "Faild", idx + 2, "testCase") else: writeResult(excelObj, caseSheet, "", idx + 2, "testCase") logger.info("用例“{}”被设置为忽略执行".format(caseNameCols[idx + 1].value)) logger.error("共{}条用例,{}条需要被执行,本次执行通过{}条".format( len(isExecuteCaseCols) - 1, requiredCaseNum, successfulCaseNum)) except Exception as e: logger.info("关键字驱动框架主程序发生异常\n异常信息:{}".format(traceback.format_exc()))
def appRankAndSearchApp(): try: excelObj = ParseExcel() excelObj.loadWorkBook(dataFilePath) caseSheet = excelObj.getSheetByName("测试用例") caseNum = excelObj.getRowsNumber(caseSheet) isExecuteCaseCols = excelObj.getColumn(caseSheet, testCase_isExecute) # 记录需要执行的用例个数 requiredCaseNum = 0 # 记录执行成功的用例个数 successfulCaseNum = 0 for idx, i in enumerate(isExecuteCaseCols[1:]): caseName = excelObj.getCellOfValue(caseSheet, rowNo=idx + 2, colsNo=testCase_testCaseName) logger.info("----------" + caseName) # 测试用例sheet中第一行为标题,无须执行 if i.value == "y": requiredCaseNum += 1 caseRow = excelObj.getRow(caseSheet, idx + 2) frameworkName = caseRow[testCase_frameworkName - 1].value stepSheetName = caseRow[testCase_testStepSheetName - 1].value if frameworkName == "关键字": logger.info("**********调用关键字驱动**********") # 根据用例的sheet名获取用例的sheet对象 stepSheet = excelObj.getSheetByName(stepSheetName) # 记录用例步骤的个数 stepNum = excelObj.getRowsNumber(stepSheet) # 记录用例步骤执行成功的个数 successfulStepNum = 0 for j in range(2, stepNum + 1): # 用例步骤中的第一行为标题,无须执行 stepRow = excelObj.getRow(stepSheet, j) # 获取用例步骤中描述 StepDescription = stepRow[caseStep_caseStepDescription - 1].value # 获取函数名 keyWord = stepRow[caseStep_keyWord - 1].value print("keyWord = ", keyWord) # 获取操作元素的定位方式 locationType = stepRow[caseStep_locationType - 1].value # 获取操作元素定位方式的表达式 locatorExpression = stepRow[caseStep_locatorExpression - 1].value # 获取函数中的参数 operatorValue = stepRow[caseStep_operatorValue - 1].value # 数值类数据从excel取出后为long型数据,转换为字符串,方便拼接 if isinstance(operatorValue, int): operatorValue = str(operatorValue) if keyWord and locationType and locatorExpression and operatorValue: step = keyWord + "('%s','%s','%s')" % ( locationType, locatorExpression, operatorValue) elif keyWord and locationType and locatorExpression: step = keyWord + "('%s','%s')" % ( locationType, locatorExpression) elif keyWord and operatorValue: step = keyWord + "('%s')" % operatorValue elif keyWord: step = keyWord + "()" try: # 用例步骤执行执行成功,写入执行结果和日志 print(step) eval(step) successfulStepNum += 1 writeResult(excelObj, stepSheet, "Pass", j, "caseStep") logger.info("执行步骤“%s”成功" % StepDescription) except Exception as err: #用例步骤执行执行成功 errPicPath = capture_screen() errMsg = traceback.format_exc() writeResult(excelObj, stepSheet, "Faild", j, "caseStep", errMsg=errMsg, errPicPath=errPicPath) logger.error( "执行步骤“%s”失败\n异常信息:%s" % (StepDescription, str(traceback.format_exc()))) if successfulStepNum == stepNum - 1: successfulCaseNum += 1 writeResult(excelObj, caseSheet, "Pass", idx + 2, "testCase") logger.info("用例“%s”执行成功" % caseName) else: writeResult(excelObj, caseSheet, "Faild", idx + 2, "testCase") logger.info("用例“%s”执行失败" % caseName) elif frameworkName == "数据": logger.info("**********调用数据驱动**********") dataSourceSheetName = caseRow[testCase_dataSourceSheetName - 1].value # print dataSourceSheetName,stepSheetName stepSheet = excelObj.getSheetByName(stepSheetName) dataSheet = excelObj.getSheetByName(dataSourceSheetName) result = searchApp(excelObj, stepSheet, dataSheet) if result: successfulCaseNum += 1 writeResult(excelObj, caseSheet, "Pass", idx + 2, "testCase") logger.info("用例“%s”执行成功" % caseName) else: writeResult(excelObj, caseSheet, "Faild", idx + 2, "testCase") logger.info("用例“%s”执行失败" % caseName) else: # 清空不需要执行用例的执行时间和执行结果, writeResult(excelObj, caseSheet, "", idx + 2, "testCase") logger.info("用例“%s”被设置为忽略执行" % caseName) logger.info("共%s条用例,%s条需要被执行,本次执行通过%s条" % (caseNum - 1, requiredCaseNum, successfulCaseNum)) except Exception as err: logger.error("驱动框架主程序发生异常\n异常信息:%s" % str(traceback.format_exc()))
def createContacts(): try: excelObj = ParseExcel() excelObj.loadWorkBook(dataFilePath) userSheet = excelObj.getSheetByName("126账号") isExecute = excelObj.getColumn(userSheet, account_isExecute) userNameCols = excelObj.getColumn(userSheet, account_userName) for idx, i in enumerate(isExecute[1:]): if i.value == 'y': userRow = excelObj.getRow(userSheet, idx + 2) userName = userRow[account_userName - 1].value passWord = str(userRow[account_passWord - 1].value) contactSheetName = userRow[account_dataSourceSheetName - 1].value driver = webdriver.Chrome() driver.maximize_window() driver.get("https://mail.126.com/") LoginAction.login(driver, userName, passWord) #断言前停顿3秒,防止页面跳转太快,断言失败 time.sleep(3) try: assert "收 信" in driver.page_source except Exception as e: logger.error("用户“{}”登录后,断言页面关键字“退出”失败\n异常信息:{}".format( userName, traceback.format_exc())) else: logger.info("用户“{}”登录后,断言页面关键字“退出”成功".format(userName)) contactSheet = excelObj.getSheetByName(contactSheetName) isExecuteAddContact = excelObj.getColumn( contactSheet, contacts_isExecute) contactNum = 0 successAddContactNum = 0 coutactPersonNameCols = excelObj.getColumn( contactSheet, contacts_contactPersonName) for id, j in enumerate(isExecuteAddContact[1:]): if j.value == 'y': contactNum += 1 contactRow = excelObj.getRow(contactSheet, id + 2) coutactPersonName = coutactPersonNameCols[id + 1].value coutactPersonEmail = contactRow[ contacts_contactPersonEmail - 1].value isStar = contactRow[contacts_isStar - 1].value countactPersonPhone = str( contactRow[contacts_contactPersonPhone - 1].value) countactPersonComment = contactRow[ contacts_contactPersonComment - 1].value assertKeyWords = contactRow[contacts_assertKeyWords - 1].value logger.info("**********开始添加联系人“%s”**********" % coutactPersonName) AddContactAction.addContact(driver, coutactPersonName, coutactPersonEmail, isStar, countactPersonPhone, countactPersonComment) time.sleep(3) try: assert assertKeyWords in driver.page_source except Exception as e: excelObj.writeCell(contactSheet, "faild", rowNo=id + 2, colsNo=contacts_testResult, style="red") excelObj.writeCellCurrentTime( contactSheet, rowNo=id + 2, colsNo=contacts_runTime, style="red") logger.error("添加联系人“{}”失败\n异常信息:{}".format( coutactPersonName, traceback.format_exc())) else: successAddContactNum += 1 excelObj.writeCell(contactSheet, "pass", rowNo=id + 2, colsNo=contacts_testResult, style="green") excelObj.writeCellCurrentTime( contactSheet, rowNo=id + 2, colsNo=contacts_runTime, style="green") logger.info( "添加联系人“{}”成功".format(coutactPersonName)) else: excelObj.writeCell(contactSheet, "", rowNo=id + 2, colsNo=contacts_runTime) excelObj.writeCell(contactSheet, "", rowNo=id + 2, colsNo=contacts_testResult) logger.info("联系人“{}”被忽略执行".format( coutactPersonNameCols[idx + 1].value)) driver.quit() if contactNum == successAddContactNum: excelObj.writeCell(userSheet, "Pass", rowNo=idx + 2, colsNo=account_testResult, style="green") else: excelObj.writeCell(userSheet, "Faild", rowNo=idx + 2, colsNo=account_testResult, style="red") else: excelObj.writeCell(userSheet, "", rowNo=idx + 2, colsNo=account_testResult) logger.info("账号“{}”被忽略执行".format(userNameCols[idx + 1].value)) except Exception as e: logger.error("数据驱动框架主程序发生异常\n异常信息:{}".format(traceback.format_exc()))
def get_page_title(self): logger.info("获取网页的标题是:%s" % self.driver.title) return self.driver.title
def click(self, selector): try: self.find_element(selector).click() logger.info("点击该按钮成功") except NameError as e: logger.info("点击该按钮失败")
def input_string(self, selector, inputContent): try: self.find_element(selector).send_keys(inputContent) logger.info("在输入框输入 %s" % inputContent) except NameError as e: logger.error("输入框无法输入 %s" % inputContent)
def get_sheet_by_index(self, index): self.ws = self.wb[self.get_sheet_name_by_index(index)] #print("设定的sheet名称是:",self.ws.title) logger.info("设定的sheet名称是:%s" % self.ws.title)
def sendRequest(): try: excelObj = ParseExcel() excelObj.loadWorkBook(dataFilePath) apiSheet = excelObj.getSheetByName(ApiSheetName) apiNameCols = excelObj.getColumn(apiSheet, API_name) apiIsExecuteCols = excelObj.getColumn(apiSheet, API_isExecute) for idx, i in enumerate(apiIsExecuteCols[1:]): apiName = apiNameCols[idx + 1].value if i.value == "y": case_total = 0 case_passNum = 0 case_ignoreNum = 0 case_failNum = 0 case_errorNum = 0 apiRow = excelObj.getRow(apiSheet, idx + 2) requestUrl = apiRow[API_requestUrl - 1].value requestMothod = apiRow[API_requestMothod - 1].value paramsType = apiRow[API_paramsType - 1].value testCaseSheetName = apiRow[API_testCaseSheetName - 1].value logger.info("----------" + apiName) testCaseSheet = excelObj.getSheetByName(testCaseSheetName) testCaseIsExecuteCols = excelObj.getColumn(testCaseSheet, TestCase_isExecute) for id, j in enumerate(testCaseIsExecuteCols[1:]): case_total += 1 try: if j.value == "y": testCaseRow = excelObj.getRow(testCaseSheet, id + 2) requestHeaders = testCaseRow[TestCase_requestHeaders - 1].value headersEncrypt = testCaseRow[TestCase_headersEncrypt - 1].value requestData = testCaseRow[TestCase_requestData - 1].value dependData = testCaseRow[TestCase_dependData - 1].value bodyEncrypt = testCaseRow[TestCase_bodyEncrypt - 1].value responseData = testCaseRow[TestCase_responseData - 1].value responseDecrypt = testCaseRow[TestCase_responseDecrypt - 1].value dependDataStore = testCaseRow[TestCase_dependDataStore - 1].value checkPoint = testCaseRow[TestCase_checkPoint - 1].value # 当请求参数中不是数值时,处理成字典 if not isinstance(requestData, int): requestData = eval(requestData) # 处理请求参数中的依赖数据 if requestData and dependData: requestData = getDependData(requestData, eval(dependData)) # 处理请求参数中的加密数据 if requestData and bodyEncrypt: requestData = bodyEncryptOper(requestData, eval(bodyEncrypt)) httpC = HttpClient() response = httpC.request(requestMothod, requestUrl, paramsType, requestData=requestData) # 接口响应结果写入用例工作表 excelObj.writeCell(testCaseSheet, response.text, rowNo=id + 2, colsNo=TestCase_responseData) # 当接口响应成功时,验证检查点是否满足 if response.status_code == 200 and checkPoint: # 获取检查点错误信息 errData = checkResult(response, eval(checkPoint)) if errData: # 接口执行失败,执行的错误结果写入到测试用例工作表 case_failNum += 1 writeResult(excelObj, testCaseSheet, "Faild", id + 2, "testcase", testCaseErrMsg=str(errData)) logger.info("接口“{}”的第“{}”条用例执行失败".format(apiName, id + 1)) else: # 接口执行成功,执行的正确结果写入到测试用例工作表 case_passNum += 1 writeResult(excelObj, testCaseSheet, "Pass", id + 2, "testcase") logger.info(u"接口“{}”的第“{}”条用例执行成功".format(apiName, id + 1)) # 当接口执行成功时,保存依赖数据到全局变量RequestData、ResponseData,供后面的接口使用 if dependDataStore: dataStore(eval(dependDataStore), testCaseSheetName, id + 2, requestSource=requestData, responseSource=response.json()) elif response.status_code != 200: # 接口响应失败,执行失败的接口写入到测试用例工作表 case_errorNum += 1 writeResult(excelObj, testCaseSheet, "Error", id + 2, "testcase", testCaseErrMsg="接口响应异常!") logger.info( "接口“{}”的第“{}”条用例执行过程出错\n错误信息:{}".format(apiName, id + 1, traceback.format_exc())) else: # 清空忽略执行的测试用例工作表数据 case_ignoreNum += 1 writeResult(excelObj, testCaseSheet, "", id + 2, "testcase") logger.info("接口“{}”的第“{}”条用例被设置为忽略执行".format(apiName, id + 1)) except Exception as e: # 接口请求中,发生异常情况,将错误结果写入测试用例工作表 case_errorNum += 1 writeResult(excelObj, testCaseSheet, "Error", id + 2, "testcase", testCaseErrMsg=traceback.format_exc()) logger.info( "接口请求发生异常情况,接口“{}”的第“{}”条用例执行过程出错\n错误信息:{}".format(apiName, id + 1, traceback.format_exc())) if case_errorNum or case_failNum: # 存在异常错误或者失败测试用例时,表示接口api执行错误,将相关的统计数据写入到接口api的工作表中 writeResult(excelObj, apiSheet, "Faild", idx + 2, "api", apiResult=[case_total, case_passNum, case_ignoreNum, case_failNum, case_errorNum]) else: writeResult(excelObj, apiSheet, "Pass", idx + 2, "api", apiResult=[case_total, case_passNum, case_ignoreNum, case_failNum, case_errorNum]) else: # 清空忽略执行api工作表的数据 writeResult(excelObj, apiSheet, "", idx + 2, "api") logger.info("接口“{}”被设置为忽略执行".format(apiName)) except Exception as e: logger.info("接口框架主程序发生异常\n异常信息:{}".format(traceback.format_exc()))
def searchApp(excelObj, stepSheet, dataSheet): try: dataIsExecuteCols = excelObj.getColumn(dataSheet, dataSource_isExecute) appNameCols = excelObj.getColumn(dataSheet, dataSource_appName) requiredDataNum = 0 successfulDataNum = 0 for idx, i in enumerate(dataIsExecuteCols[1:]): if i.value == "y": requiredDataNum += 1 successfulStepNum = 0 logger.info("开始搜索APP“{}”".format(appNameCols[idx + 1].value)) stepNum = excelObj.getRowsNumber(stepSheet) for j in range(2, stepNum + 1): # 用例步骤中的第一行为标题,无须执行 stepRow = excelObj.getRow(stepSheet, j) # 获取用例步骤中描述 stepDescription = stepRow[caseStep_caseStepDescription - 1].value # 获取函数名 keyWord = stepRow[caseStep_keyWord - 1].value # 获取操作元素的定位方式 locationType = stepRow[caseStep_locationType - 1].value # 获取操作元素定位方式的表达式 locatorExpression = stepRow[caseStep_locatorExpression - 1].value # 获取函数中的参数 operatorValue = stepRow[caseStep_operatorValue - 1].value if isinstance(operatorValue, int): # 数值类数据从excel取出后为int型数据,转换为字符串,方便拼接 operatorValue = str(operatorValue) if operatorValue and operatorValue.isalpha(): # 如果operatorValue为字母时,则根据坐标在数据源工作表中取操作值 operatorValue = excelObj.getCellOfValue( dataSheet, coordinate=operatorValue + str(idx + 2)) if keyWord and locationType and locatorExpression and operatorValue: step = keyWord + "('{}','{}','{}')".format( locationType, locatorExpression, operatorValue) elif keyWord and locationType and locatorExpression: step = keyWord + "('{}','{}')".format( locationType, locatorExpression) elif keyWord and operatorValue: step = keyWord + "('{}')".format(operatorValue) else: step = keyWord + "()" try: # 用例步骤执行执行成功,写入执行结果和日志 eval(step) successfulStepNum += 1 logger.info("执行步骤“{}”成功".format(stepDescription)) except Exception as e: # 用例步骤执行执行失败 logger.error(u"执行步骤“{}”失败\n异常信息:{}".format( stepDescription, traceback.format_exc())) if successfulStepNum == stepNum - 1: writeResult(excelObj, dataSheet, "Pass", idx + 2, "dataSheet") successfulDataNum += 1 else: writeResult(excelObj, dataSheet, "Faild", idx + 2, "dataSheet") else: # 清空不需要执行的数据源中的执行时间和执行结果 writeResult(excelObj, dataSheet, "", idx + 2, "dataSheet") logger.info("APP“{}”被设置为忽略执行".format(appNameCols[idx + 1].value)) if requiredDataNum == successfulDataNum: return 1 return 0 except Exception as e: logger.info("数据驱动框架主程序发生异常\n异常信息:{}" % (traceback.format_exc()))
def data_handler(requestData): if re.search(r"\$\{unique_num\d+\}", requestData): # 匹配用户名参数,即"${www}"的格式 var_name = re.search(r"\$\{(unique_num\d+)\}", requestData).group(1) # 获取用户名参数 #print("var_name:%s" % var_name) logger.info("var_name:%s" % var_name) var_value = get_unique_number_value(var_name) #print("var_value: %s" % var_value) logger.info("var_value: %s" % var_value) requestBody = re.sub(r"\$\{unique_num\d+\}", str(var_value), requestData) var_name = var_name.split("_")[1] #print("var_name: %s" % var_name) logger.info("var_name: %s" % var_name) global_vars[var_name] = var_value #print("global_vars: %s" % str(global_vars)) logger.info("global_vars: %s" % str(global_vars)) if re.search(r"\$\{\w+\(.+\)\}", requestData): # 匹配密码参数,即"${xxx()}"的格式 var_pass = re.search(r"\$\{(\w+\(.+\))\}", requestData).group(1) # 获取密码参数 #print("var_pass: %s" % var_pass) logger.info("var_pass: %s" % var_pass) #print("eval(var_pass): %s" % eval(var_pass)) logger.info("eval(var_pass): %s" % eval(var_pass)) requestData = re.sub(r"\$\{\w+\(.+\)\}", eval(var_pass), requestData) # 将requestBody里面的参数内容通过eval修改为实际变量值 #print("requestBody after replace: %s" % requestData) # requestBody是拿到的请求时发送的数据 logger.info("requestBody after replace: %s" % requestData) if re.search(r"\$\{(\w+)\}", requestData): #print("all mached data: ", re.findall(r"\$\{(\w+)\}", requestData)) for var_name in re.findall(r"\$\{(\w+)\}", requestData): #print("替换前 data: ", requestData) requestData = re.sub(r"\$\{%s\}" % var_name, str(global_vars[var_name]), requestData) #print("替换后 data:", requestData ) return requestData
def sleep(self, seconds): time.sleep(seconds) logger.info("等待 %s 秒" % seconds)
def api_request(url, request_method, request_content): if request_method == "get": try: if isinstance(request_content, dict): #print("请求的接口地址是:%s" %url) logger.info("请求的接口地址是:%s" % url) #print("请求的数据是:%s" %request_content) logger.info("请求的数据是:%s" % request_content) r = requests.get(url, params=json.dumps(request_content)) else: r = requests.get(url + str(request_content)) #print("请求的接口地址是:%s" %r.url) logger.warning("请求的接口地址是:%s" % r.url) #print("请求的数据是:%s" %request_content) logger.warning("请求的数据是:%s" % request_content) except BaseException as e: #print("get 方法请求发生异常:请求的url是:%s,请求的内容是:%s\n发生的异常信息如下:%s"%(url,request_content,e)) logger.debug(e) r = None return r elif request_method == "post": try: if isinstance(request_content, dict): #print("请求的接口地址是:%s" %url) logger.info("请求的接口地址是:%s" % url) #print("请求的数据是;%s" %json.dumps(request_content)) logger.info( json.dumps("请求的数据是;%s" % json.dumps(request_content))) r = requests.post(url, data=json.dumps(request_content)) else: raise ValueError except ValueError as e: #print("post方法请求发生异常:请求的url是%s,请求的内容是%s\n发生的异常信息如下:%s" %(url,request_content,e)) logger.debug(e) r = None return r elif request_method == "put": try: if isinstance(request_content, dict): #print("请求的接口地址是:%s"%url) logger.info("请求的接口地址是:%s" % url) #print("请求的数据是:%s"%json.dumps(request_content)) logger.info("请求的数据是:%s" % json.dumps(request_content)) r = requests.put(url, data=json.dumps(request_content)) else: raise ValueError except ValueError as e: #print("put 方法请求发生异常:请求的url是%s,请求的内容是%s\n发生异常信息如下:"%(url,request_content,e)) logger.debug(e) r = None return r