网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
一、接口基础
接口测试是对系统和组件之间的接口进行测试,主要是效验数据的交换,传递和控制管理过程,以及相互逻辑依赖关系。其中接口协议分为HTTP,RPC,Webservice,Dubbo,RESTful等类型。
接口测试流程
1、需求评审,熟悉业务和需求
2、开发提供接口文档
3、编写接口测试用例
4、用例评审
5、提测后开始测试
6、提交测试报告
两种常见的 HTTP 请求方法:GET 和 POST
二、项目说明
本框架是一套基于Python+Pytest+Requests+Allure+Jenkins而设计的数据驱动接口自动化测试的框架。
技术栈
Python、Pytest、Requests、Pactverity、Excel、Json、Mysql、Allure、Logbook、Git、Jenkins
三、接口测试框架结构图
四、项目功能
Python+Pytest+Allure+Jenkins接口自动化框架,实现Excel或Json维护测试用例,支持数据库操作,利用封装的请求基类调取相应的测试用例接口,获取配置文件中的环境地址与环境变量,
结合Pytest进行单元测试,使用LogBook进行记录日志,并生成allure测试报告,最后进行Jenkins集成项目实现集成部署,并发送测试报告邮件。
五、代码设计与功能说明
1、工具类封装
1.1、log日志
项目中的log日志是logbook进行日志记录的,方便测试开发调试时进行排错纠正或修复优化。日志可选择是否打印在屏幕上即运行时是否在终端输出打印。日志格式输出可调整。
handle_log.py部分源码
def log_type(record, handler):
log = "[{date}] [{level}] [{filename}] [{func_name}] [{lineno}] {msg}".format(
date=record.time, # 日志时间
level=record.level_name, # 日志等级
filename=os.path.split(record.filename)[-1], # 文件名
func_name=record.func_name, # 函数名
lineno=record.lineno, # 行号
msg=record.message # 日志内容
)
return log
# 日志存放路径
LOG_DIR = BasePath + '/log'
print(LOG_DIR)
if not os.path.exists(LOG_DIR):
os.makedirs(LOG_DIR)
# 日志打印到屏幕
log_std = ColorizedStderrHandler(bubble=True)
log_std.formatter = log_type
# 日志打印到文件
log_file = TimedRotatingFileHandler(
os.path.join(LOG_DIR, '%s.log' % 'log'), date_format='%Y-%m-%d', bubble=True, encoding='utf-8')
log_file.formatter = log_type
# 脚本日志
run_log = Logger("global_log")
def init_logger():
logbook.set_datetime_format("local")
run_log.handlers = []
run_log.handlers.append(log_file)
run_log.handlers.append(log_std)
打印在终端的日志,如下图所示。
同时运行项目后,会在项目文件log中自动生成一个以当天日期命名的log文件。点击log日志文件可查看日志详情即项目运行时所记录的日志或报错日志。如下图所示。
1.2、配置文件
项目中涉及到一些配置文件如username、password或环境变量时,我们可通过配置文件来获取配置值。通过配置文件中key与value的定义来确定获取配置文件的值。
handle_init.py部分源码
class HandleInit:
# 读取配置文件
def load_ini(self):
file_path = BasePath + "/config/config.ini"
cf = configparser.ConfigParser()
cf.read(file_path, encoding='UTF-8')
return cf
# 获取ini里面对应key的value
def get_value(self, key, node=None):
if node == None:
node = 'Test'
cf = self.load_ini()
try:
data = cf.get(node, key)
logger.info('获取配置文件的值,node:{},key:{}, data:{}'.format(node, key, data))
except Exception:
logger.exception('没有获取到对应的值,node:{},key:{}'.format(node, key))
data = None
return data
获取配置文件中的值日志如下图所示。
1.3、Api接口请求
获取相关测试用例及接口用例配置,记录请求相关参数的日志,定义Allure测试报告的步骤。
handle_apirequest.py部分代码
class ApiRequest:
def api_request(self, base_url, test_case_data, case_data):
get_name = None
get_url = None
get_method = None
get_headers = None
get_cookies = None
get_case_name = None
get_case_params = None
response_data = None
try:
get_name = test_case_data['config']['name']
get_url = base_url + test_case_data['config']['url']
get_method = test_case_data['config']['method']
get_headers = test_case_data['config']['headers']
get_cookies = test_case_data['config']['cookies']
except Exception as e:
logger.exception('获取用例基本信息失败,{}'.format(e))
try:
get_case_name = case_data['name']
get_case_params = case_data['params']
except Exception as e:
logger.exception('获取测试用例信息失败,{}'.format(e))
with allure.step("请求接口:%s,请求地址:%s,请求方法:%s,请求头:%s,请求Cookies:%s" % (
get_name, get_url, get_method, get_headers, get_cookies)):
allure.attach("接口用例描述:", "{0}".format(get_case_name))
allure.attach("接口用例请求参数:", "{0}".format(get_case_params))
logger.info(
'请求接口名:%r,请求地址:%r,请求方法:%r,请求头:%r,请求Cookies:%r' %\
1.4、Excel数据处理
1.4.1、Excel测试用例
测试用例中维护在Excel文件中,类中定义如何获取Excel中的相关数据(如获取某个单元格的内容,获取单元格的行数,以及将数据写入Excel中等操作)。
handle_exceldata.py部分源码
1 class OperationExcel:
2 def __init__(self, file_name=None, sheet_id=None):
3 if file_name:
4 self.file_name = file_name
5 self.sheet_id = sheet_id
6 else:
7 self.file_name = ''
8 self.sheet_id = 0
9 self.data = self.get_data()
10
11 # 获取sheets的内容
12 def get_data(self):
13 data = xlrd.open_workbook(self.file_name)
14 tables = data.sheets()[self.sheet_id]
15 return tables
16
17 # 获取单元格的行数
18 def get_lines(self):
19 tables = self.data
20 return tables.nrows
21
22 # 获取某一个单元格的内容
23 def get_cell_value(self, row, col):
24 return self.data.cell_value(row, col)
1.5、Json数据处理
1.5.1、Json测试用例
1 {
2 "config":{
3 "name":"post接口名",
4 "url":"/langdetect",
5 "method":"POST",
6 "headers":{
7 "Content-Type":"application/json"
8 },
9 "cookies":{
10
11 }
12 },
13 "testcase":[
14 {
15 "name":"测试用例1",
16 "params":{
17 "query":"测试"
18 },
19 "validate":[
20 {
21 "check":"status_code",
22 "comparator":"eq",
23 "expect":"200"
24 }
25 ]
26 },
27 {
28 "name":"测试用例2",
29 "params":{
30 "query":"python"
31 },
32 "validate":[
33 {
34 "check":"msg",
35 "comparator":"eq",
36 "expect":"success"
37 }
38 ]
39 }
40 ]
41 }
1.5.2、Json用例处理
获取Json文件中里具体字段的值。
handle.json.py部分源码
1 class HandleJson:
2 # 读取json文件
3 def load_json(self, file_name):
4 if file_name == None:
5 file_path = ""
6 else:
7 file_path = file_name
8 try:
9 with open(file_path, encoding='UTF-8') as f:
10 data = json.load(f)
11 return data
12 except Exception:
13 print("未找到json文件")
14 return {}
15
16 # 读取json文件里具体的字段值
17 def getJson_value(self, key, file_name):
18 if file_name == None:
19 return ""
20 jsonData = self.load_json(file_name)
21 if key == None:
22 getJsonValue = ""
23 else:
24 getJsonValue = jsonData.get(key)
25 return getJsonValue
2、基类封装
2.1、请求基类封装
接口支持Get、Post请求,调用requests请求来实现接口的调用与返回。接口参数包括,接口地址、接口请求参数、cookie参数、header参数。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
ookie参数、header参数。
[外链图片转存中…(img-G2K1jQHk-1715279828145)]
[外链图片转存中…(img-kIGZsr9P-1715279828145)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!