百度快照举报网站,中国基建人才网,网站建设可以用什么语言,网站 猜你喜欢 怎么做目录#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结#xff08;尾部小惊喜#xff09; 前言
util 包
util 包… 目录导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结尾部小惊喜 前言
util 包
util 包属于第一层的测试工具层用于实现测试过程中调用的工具类方法例如读取配置文件、页面元素的操作方法、操作 Excel 文件、生成测试报告、发送邮件等。
global_var.py 本模块用于定义测试过程中所需的全局变量。
import osPROJECT_DIR os.path.dirname(os.path.dirname(os.path.abspath(__file__)))# APP配置信息路径
INI_FILE_PATH os.path.join(PROJECT_DIR, conf, desired_caps_config.ini)# 异常截图路径
EXCEPION_PIC_PATH os.path.join(PROJECT_DIR, exception_pic)# 日志配置文件路径
LOG_CONF_FILE_PATH os.path.join(PROJECT_DIR, conf, logger.conf)# 测试数据文件路径
TEST_DATA_FILE_PATH os.path.join(PROJECT_DIR, test_data, test_case.xlsx)# 测试报告存放路径
TEST_REPORT_FILE_DIR os.path.join(PROJECT_DIR, test_report)# Appium server地址
APPIUM_SERVER http://localhost:4723/wd/hub# 测试数据文件中测试用例sheet中部分列对应的数字序号
TESTCASE_CASE_NAME_COL_NO 0
TESTCASE_FRAMEWORK_TYPE_COL_NO 1
TESTCASE_CASE_STEP_SHEET_NAME_COL_NO 2
TESTCASE_DATA_SOURCE_SHEET_NAME_COL_NO 3
TESTCASE_IS_EXECUTE_COL_NO 4
TESTCASE_TEST_TIME_COL_NO 5
TESTCASE_TEST_RESULT_COL_NO 6# 用例步骤sheet中部分列对应的数字序号
CASESTEP_NAME_COL_NO 0
CASESTEP_ACTION_COL_NO 1
CASESTEP_LOCATE_METHOD_COL_NO 2
CASESTEP_LOCATE_EXPRESSION_COL_NO 3
CASESTEP_OPERATION_VALUE_COL_NO 4
CASESTEP_IS_EXECUTE_COL_NO 5
CASESTEP_TEST_TIME_COL_NO 6
CASESTEP_TEST_RESULT_COL_NO 7
CASESTEP_EXCEPTION_INFO_COL_NO 8
CASESTEP_EXCEPTION_PIC_DIR_COL_NO 9# 数据源sheet中是否执行列对应的数字编号
DATASOURCE_DATA 0
DATASOURCE_KEYWORD 1
DATASOURCE_IS_EXECUTE 2
DATASOURCE_TEST_TIME 3
DATASOURCE_TEST_RESULT 4# 测试执行结果统计
TOTAL_CASE 0
PASS_CASE 0
FAIL_CASE 0if __name__ __main__:print(PROJECT_DIR)find_element_util.py
本模块封装了基于显式等待的界面元素定位方法。
from selenium.webdriver.support.ui import WebDriverWait# 显式等待一个元素
def find_element(driver, locate_method, locate_exp):# 显式等待对象最多等10秒每0.2秒判断一次等待的条件return WebDriverWait(driver, 10, 0.2).until(lambda x: x.find_element(locate_method, locate_exp))# 显式等待一组元素
def find_elements(driver, locate_method, locate_exp):# 显式等待对象最多等10秒每0.2秒判断一次等待的条件return WebDriverWait(driver, 10, 0.2).until(lambda x: x.find_elements(locate_method, locate_exp))excel_util.py
本模块封装了对 excel 的读写操作openpyxl 版本3.0.4。
import os
from openpyxl import load_workbook
from openpyxl.styles import PatternFill, Font, Side, Border
from util.datetime_util import *
from util.global_var import *
from util.log_util import *# 支持excel读写操作的工具类
class Excel:# 初始化读取excel文件def __init__(self, file_path):if not os.path.exists(file_path):returnself.wb load_workbook(file_path)# 初始化默认sheetself.ws self.wb.activeself.data_file_path file_path# 初始化颜色字典供设置样式用self.color_dict {red: FFFF3030, green: FF008B00}def get_all_sheet(self):return self.wb.get_sheet_names()# 打开指定sheetdef get_sheet(self, sheet_name):if sheet_name not in self.get_all_sheet():print(sheet名称【%s】不存在 % sheet_name)returnself.ws self.wb.get_sheet_by_name(sheet_name)return True# 获取最大行号def get_max_row_no(self):# openpyxl的API的行、列索引默认都从1开始return self.ws.max_row# 获取最大列号def get_max_col_no(self):return self.ws.max_column# 获取所有行数据def get_all_row_data(self, head_lineTrue):# 是否需要标题行数据的标识默认需要if head_line:min_row 1 # 行号从1开始即1为标题行else:min_row 2result []# min_rowNone默认获取标题行数据for row in self.ws.iter_rows(min_rowmin_row, max_rowself.get_max_row_no(), max_colself.get_max_col_no()):result.append([cell.value for cell in row])return result# 获取指定行数据def get_row_data(self, row_num):# 0 为标题行return [cell.value for cell in self.ws[row_num1]]# 获取指定列数据def get_col_data(self, col_num):# 索引从0开始return [cell.value for cell in tuple(self.ws.columns)[col_num]]# 追加行数据且可以设置样式def write_row_data(self, data, font_colorNone, borderTrue, fill_colorNone):if not isinstance(data, (list, tuple)):print(写入数据失败数据不为列表或元组类型【%s】 % data)self.ws.append(data)# 设置字体颜色if font_color:if font_color.lower() in self.color_dict.keys():font_color self.color_dict[font_color]# 设置单元格填充颜色if fill_color:if fill_color.lower() in self.color_dict.keys():fill_color self.color_dict[fill_color]# 设置单元格边框if border:bd Side(stylethin, color000000)# 记录数据长度否则会默认与之前行最长数据行的长度相同导致样式超过了该行实际长度count 0for cell in self.ws[self.get_max_row_no()]:# 设置完该行的实际数据长度样式后则退出if count len(data) - 1:breakif font_color:cell.font Font(colorfont_color)# 如果没有设置字体颜色则默认给执行结果添加字体颜色else:if cell.value is not None and isinstance(cell.value, str):if cell.value.lower() pass or cell.value 成功:cell.font Font(colorself.color_dict[green])elif cell.value.lower() fail or cell.value 失败:cell.font Font(colorself.color_dict[red])if border:cell.border Border(leftbd, rightbd, topbd, bottombd)if fill_color:cell.fill PatternFill(fill_typesolid, fgColorfill_color)count 1# 指定行插入数据行索引从0开始def insert_row_data(self, row_no, data, font_colorNone, borderTrue, fill_colorNone):if not isinstance(data, (list, tuple)):print(写入数据失败数据不为列表或元组类型【%s】 % data)for idx, cell in enumerate(self.ws[row_no1]): # 此处行索引从1开始cell.value data[idx]# 生成写入了测试结果的excel数据文件def save(self, save_file_name, timestamp):save_dir os.path.join(TEST_REPORT_FILE_DIR, get_chinese_date())if not os.path.exists(save_dir):os.mkdir(save_dir)save_file os.path.join(save_dir, save_file_name _ timestamp .xlsx)self.wb.save(save_file)info(生成测试结果文件%s % save_file)return save_fileif __name__ __main__:from util.global_var import *from util.datetime_util import *excel Excel(TEST_DATA_FILE_PATH)excel.get_sheet(测试结果统计)# print(excel.get_all_row_data())# excel.write_row_data([4, None, 嘻哈], green, True, red)excel.insert_row_data(1, [1,2,3])excel.save(get_timestamp())ini_reader.py
本模块封装了对 ini 配置文件的读取操作。
import os
import configparser# 读取ini文件的工具类
class IniParser:# 初始化打开ini文件def __init__(self, file_path):if not os.path.exists(file_path):print(ini文件【%s】不存在 % file_path)returnself.cf configparser.ConfigParser()self.cf.read(file_path, encodingutf-8)# 获取所有分组def get_sections(self):return self.cf.sections()# 获取指定分组的所有键def get_options(self, section):return self.cf.options(section) # 注意获取的键会自动转小写# 获取指定分组的所有键值对def get_items(self, section):return dict(self.cf.items(section)) # 注意获取的键会自动转小写# 获取指定分组指定键的值def get_value(self, section, option):return self.cf.get(section, option)if __name__ __main__:from util.global_var import *p IniParser(INI_FILE_PATH)print(p.get_sections())print(p.get_options(desired_caps))print(p.get_items(desired_caps))print(p.get_value(desired_caps, deviceName))email_util.py
本模块封装了邮件发送功能。示例代码中的用户名/密码已隐藏
import yagmail
import traceback
from util.log_util import *def send_mail(attachments_report_name, receiver, subject, content):try:# 连接邮箱服务器# 注意若使用QQ邮箱则password为授权码而非邮箱密码使用其它邮箱则为邮箱密码# encoding设置为GBK否则中文附件名会乱码yag yagmail.SMTP(user*****163.com, password*****, hostsmtp.163.com, encodingGBK)# 收件人、标题、正文、附件若多个收件人或多个附件则可使用列表yag.send(toreceiver, subjectsubject, contentscontent, attachmentsattachments_report_name)# 可简写yag.send(****163.com, subject, contents, report)info(测试报告邮件发送成功!【邮件标题%s】【邮件附件%s】【收件人%s】 % (subject, attachments_report_name, receiver))except:error(测试报告邮件发送失败!【邮件标题%s】【邮件附件%s】【收件人%s】 % (subject, attachments_report_name, receiver))error(traceback.format_exc())if __name__ __main__:send_mail(e:\\code.txt, xxxxxxqq.com, 测试邮件, 正文)datetime_util.py
本模块实现了获取各种格式的当前日期时间。
import time# 返回中文格式的日期xxxx年xx月xx日
def get_chinese_date():year time.localtime().tm_yearif len(str(year)) 1:year 0 str(year)month time.localtime().tm_monif len(str(month)) 1:month 0 str(month)day time.localtime().tm_mdayif len(str(day)) 1:day 0 str(day)return {}年{}月{}日.format(year, month, day)# 返回英文格式的日期xxxx/xx/xx
def get_english_date():year time.localtime().tm_yearif len(str(year)) 1:year 0 str(year)month time.localtime().tm_monif len(str(month)) 1:month 0 str(month)day time.localtime().tm_mdayif len(str(day)) 1:day 0 str(day)return {}/{}/{}.format(year, month, day)# 返回中文格式的时间xx时xx分xx秒
def get_chinese_time():hour time.localtime().tm_hourif len(str(hour)) 1:hour 0 str(hour)minute time.localtime().tm_minif len(str(minute)) 1:minute 0 str(minute)second time.localtime().tm_secif len(str(second)) 1:second 0 str(second)return {}时{}分{}秒.format(hour, minute, second)# 返回英文格式的时间xx:xx:xx
def get_english_time():hour time.localtime().tm_hourif len(str(hour)) 1:hour 0 str(hour)minute time.localtime().tm_minif len(str(minute)) 1:minute 0 str(minute)second time.localtime().tm_secif len(str(second)) 1:second 0 str(second)return {}:{}:{}.format(hour, minute, second)# 返回中文格式的日期时间
def get_chinese_datetime():return get_chinese_date() get_chinese_time()# 返回英文格式的日期时间
def get_english_datetime():return get_english_date() get_english_time()# 返回时间戳
def get_timestamp():year time.localtime().tm_yearif len(str(year)) 1:year 0 str(year)month time.localtime().tm_monif len(str(month)) 1:month 0 str(month)day time.localtime().tm_mdayif len(str(day)) 1:day 0 str(day)hour time.localtime().tm_hourif len(str(hour)) 1:hour 0 str(hour)minute time.localtime().tm_minif len(str(minute)) 1:minute 0 str(minute)second time.localtime().tm_secif len(str(second)) 1:second 0 str(second)return {}{}{}_{}{}{}.format(year, month, day, hour, minute, second)if __name__ __main__:print(get_chinese_datetime())print(get_english_datetime())get_desired_caps.py
本模块实现了获取 ini 配置文件中的 Appium 创建 Session 的配置信息。
from util.ini_reader import IniParser
from util.global_var import INI_FILE_PATHdef get_desired_caps():pcf IniParser(INI_FILE_PATH)items pcf.get_items(desired_caps) # 获取的键会自动转成小写desired_caps {platformName: items.get(platformname),platformVersion: items.get(platformversion),deviceName: items.get(devicename),appPackage: items.get(apppackage),appActivity: items.get(appactivity),unicodeKeyboard: items.get(unicodekeyboard),autoAcceptAlerts: items.get(autoacceptalerts),resetKeyboard: items.get(resetkeyboard),noReset: items.get(noreset),newCommandTimeout: items.get(newcommandtimeout)}return desired_capsif __name__ __main__:from util.global_var import *print(get_desired_caps())log_util.py
封装了日志打印输出、级别设定等功能。
import logging
import logging.config
from util.global_var import *# 日志配置文件多个logger每个logger指定不同的handler
# handler设定了日志输出行的格式
# 以及设定写日志到文件是否回滚还是到屏幕
# 还定了打印日志的级别
logging.config.fileConfig(LOG_CONF_FILE_PATH)
logger logging.getLogger(example01)def debug(message):logging.debug(message)def info(message):logging.info(message)def warning(message):logging.warning(message)def error(message):logging.error(message)if __name__ __main__:debug(hi)info(gloryroad)warning(hello)error(这是一个error日志)report_util.py
生成测试结果文件并发送邮件。
from util.email_util import send_mail
from util.log_util import *
from util.datetime_util import *# 生成测试报告并发送邮件
def create_excel_report_and_send_email(excel_obj, receiver, subject, content)::param excel_obj: excel对象用于保存文件:param timestamp: 用于文件命名的时间戳:return: 返回excel测试报告文件名time_stamp get_timestamp()report_path excel_obj.save(subject, time_stamp)send_mail(report_path, receiver, subject_time_stamp, content)conf 目录
conf 目录属于第一层测试工具层用于存储各配置文件。
desired_caps_config.ini 本配置文件存储了 Appium 创建 Session 的配置信息。
[desired_caps]
platformNameAndroid
platformVersion6
deviceName3DN6T16B26001805
appPackagecom.xsteach.appedu
appActivitycom.xsteach.appedu.StartActivity
unicodeKeyboardTrue
autoAcceptAlertsTrue
resetKeyboardTrue
noResetTrue
newCommandTimeout6000logger.conf 本配置文件用于日志功能的具体配置。
###############################################
[loggers]
keysroot,example01,example02
[logger_root]
levelDEBUG
handlershand01,hand02[logger_example01]
handlershand01,hand02
qualnameexample01
propagate0[logger_example02]
handlershand01,hand03
qualnameexample02
propagate0###############################################
[handlers]
keyshand01,hand02,hand03[handler_hand01]
classStreamHandler
levelINFO
formatterform01
args(sys.stderr,)[handler_hand02]
classFileHandler
levelDEBUG
formatterform01
args(E:\\pycharm_project_dir\\AppAutoTest\\log\\app_test.log, a)[handler_hand03]
classhandlers.RotatingFileHandler
levelINFO
formatterform01
args(E:\\pycharm_project_dir\\AppAutoTest\\log\\app_test.log, a, 10*1024*1024, 5)###############################################
[formatters]
keysform01,form02[formatter_form01]
format%(asctime)s [%(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:%Stest_data 目录
test_data 目录用于存放测试数据文件Excel存储了用例步骤、用例执行关键字、数据源等测试数据。 main.py
本模块是本框架的运行主入口属于第四层“测试场景层”将测试用例组织成测试场景实现各种级别 cases 的管理如冒烟回归等测试场景。
基于 business_process/main_process.py 中的模块用例 sheet 执行函数或主 sheet 执行函数组装测试场景。
可直接用代码组装测试场景也可根据 excel 数据文件的用例集合和用例步骤的维护来设定测试场景。 完成测试执行后生成测试结果文件并发送邮件。
from bussiness_process.main_process import *
from util.report_util import *# 组装测试场景
# 冒烟测试
def smoke_test(report_name):excel, _ suite_process(TEST_DATA_FILE_PATH, 进入主页)excel, _ suite_process(excel, 登录)excel, _ suite_process(excel, 退出)# 生成测试报告并发送邮件create_excel_report_and_send_email(excel, [xxxxxxxxx163.com, xxxxxxxxqq.com], report_name, 请查收附件app自动化测试报告)# 全量测试执行主sheet的用例集
def suite_test(report_name):excel main_suite_process(TEST_DATA_FILE_PATH, 测试用例集)create_excel_report_and_send_email(excel, [xxxxxxx163.com, xxxxxxxqq.com], report_name, 请查收附件app自动化测试报告)if __name__ __main__:# smoke_test(APP自动化测试报告_冒烟测试)suite_test(APP自动化测试报告_全量测试)test_report 目录
本目录用于存放测试结果文件。 exception_pic 目录
本目录用于存放失败用例的截图。 log 目录
本目录用于存放日志输出文件日志内容同时也会输出到控制台。 log/app_test.log 下面是我整理的2023年最全的软件测试工程师学习知识架构体系图
一、Python编程入门到精通 二、接口自动化项目实战 三、Web自动化项目实战 四、App自动化项目实战 五、一线大厂简历 六、测试开发DevOps体系 七、常用自动化测试工具 八、JMeter性能测试 九、总结尾部小惊喜
不论起点如何只要拥有激情与毅力奋斗就是通往成功的道路不论困难多大只要心怀信念与勇气挑战就是成长的机会。努力奋斗追逐梦想将创造属于自己的辉煌人生
每一次努力都是迈向辉煌的一步每一次奋斗都是砥砺前行的力量。不辜负青春铭记初心扬起梦想的风帆执着追逐终将驶向成功的彼岸。
不论身处何地只要心怀梦想就别停止追逐不管困难多大只要坚持奋斗就能开创未来。披荆斩棘勇往直前舞动青春的旋律绽放人生的辉煌