python实现接口自动化测试
python实现接口自动化测试
(周六日可以按照用例编写相关的接口测试用例,如果有验证码之类,给提供数据库查询或者固定验证码的可以。
web UI的也可以按照这个来,需要截图的地方,html报告中可查看执行过程中的截图)
模块分类
1、common(公用类)
2、config(配置类)
3、project(各个系统封装的API方法)
4、API_TC(测试案例)
5、TestFile(需要上传的或者其它使用的文件)
7、TestReport(保存执行结果)
common
主要是一些公用的类
-
api_common ,
api_common.py
封装了读取表格案例的request方法
import json
import re
import requests
import xlrd
from requests import packages
from common import tool
from config.config import *
def str_cmp(str1, str2):
cmp_result = bool(re.fullmatch(str1, str2, re.IGNORECASE))
return cmp_result
class RequestMethod(object):
def __init__(self, request_url, json_data, headers, data_type, assert_content):
packages.urllib3.disable_warnings()
self.request_url = request_url
self.json_data = json_data
self.data_type = data_type
self.assert_content = assert_content
if type(headers).__name__ == 'dict':
self.headers = headers
else:
self.headers = eval(headers) # 将字符串转化为字典
def post(self, cookies, *file):
if self.data_type == "file":
if len(file) > 1:
data = eval(self.json_data) # 使用字典
file_path = file[0]
file = {
file[1]: open(file_path, 'rb')
}
response = requests.post(self.request_url,
data=data,
files=file,
cookies=cookies)
else:
data = eval(self.json_data) # 使用字典
file_path = file[0]
file = {
'file': open(file_path, 'rb')
}
response = requests.post(self.request_url,
data=data,
files=file,
cookies=cookies)
else:
if self.data_type == "form":
data = eval(self.json_data) # 使用字典
if self.data_type == "json":
data = json.dumps(eval(self.json_data)) # 将字典解析为json
response = requests.post(self.request_url,
data=data,
headers=self.headers,
cookies=cookies)
if bool(tool.str_cmp("image/", response.headers['Content-Type'])):
result_content = ('生成图片验证码').encode('utf-8')
else:
if response.headers['Content-Type'] == 'APPLICATION/OCTET-STREAM':
result_content = response.content
else:
result_content = response.content.decode("utf-8")
result_code = response.status_code
result_session = response.cookies.get_dict()
result_dict = {"result_content": result_content,
"result_code": result_code,
"result_session": result_session}
if response.headers['Content-Type'] != 'APPLICATION/OCTET-STREAM':
print(result_content)
if self.assert_content != "":
try:
assert (self.assert_content in result_content)
except Exception as e:
print(self.assert_content)
assert False
return result_dict
def get(self, cookies):
data = eval(self.json_data) # 使用字典
response = requests.get(self.request_url,
params=data,
headers=self.headers,
cookies=cookies)
if bool(tool.str_cmp("image/", response.headers['Content-Type'])):
result_content = ('生成图片验证码').encode('utf-8')
elif bool(tool.str_cmp("text/", response.headers['Content-Type'])):
result_content = ('导出').encode('utf-8')
else:
if response.headers['Content-Type'] == 'APPLICATION/OCTET-STREAM':
result_content = response.content
else:
result_content = response.content.decode("utf-8")
# result_json = response.json()
result_code = response.status_code
result_session = response.cookies.get_dict()
result_dict = {"result_content": result_content,
"result_code": result_code,
# "result_json": result_json,
"result_session": result_session}
if response.headers['Content-Type'] != 'APPLICATION/OCTET-STREAM':
print(result_content)
if self.assert_content != "":
try:
assert (self.assert_content in result_content)
except Exception as e:
print(self.assert_content)
assert False
return result_dict
class ReadExcel(object):
def __init__(self, file_path, sheet_name):
self.file_path = file_path
self.sheet_name = sheet_name
self.table = self.load_excel()
self.ncols = self.table.ncols
self.nrows = self.table.nrows
def load_excel(self):
try:
data = xlrd.open_workbook(self.file_path)
table = data.sheet_by_name(self.sheet_name)
return table
except Exception as e:
print(u"读表格错误")
print(e)
def get_col_number(self, row_number, row_name):
# 表头名字为row_name的第row_number行,所对应的列1
for i in range(self.ncols):
if str_cmp(self.table.row_values(row_number)[i], row_name):
return i
def get_value(self, row_number, row_name):
# 表头名字为row_name的第row_number行,获得这一列
try:
head_number = self.get_col_number(0, row_name)
value = self.table.col_values(head_number)[row_number]
return value
except Exception as e:
print("getCellData(%s,%s)" % (row_number, row_name))
print(e)
def for_test(self, number):
url = (get_var("Origin", self.sheet_name) + self.get_value(number, u"请求URL"))
data_list = [url,
self.get_value(number, u"参数"),
self.get_value(number, u"请求头"),
self.get_value(number, "数据格式"),
self.get_value(number, "响应信息")]
return data_list
def request_test(self, i, *par, **headers):
default_header = eval(self.for_test(i)[2])
if len(headers) > 0:
default_header.update(headers)
header = default_header
# else:
# header = default_header
data = self.for_test(i)[1] % par
print(self.for_test(i)[0], data, header)
return RequestMethod(self.for_test(i)[0],
data,
header,
self.for_test(i)[3],
self.for_test(i)[4]
)
工作中常用的方法:
1、用正则获取报文信息的并传递做为参数使用
2、按要求修改表格中数据,并保存
# from common import common
import datetime
import os
import re
import shutil
import time
from openpyxl import load_workbook
# 比对字符串,并打印结果
def str_cmp(str1, str2, str3="可以填写信息"):
cmp_result = re.search(str(str1), str(str2), re.IGNORECASE)
return cmp_result
# if cmp_result is not None:
# return cmp_result
# else:
# print(str3)
# print("预期结果:" + str1)
# print("实际结果:" + str2)
# 正则表达式
def regular(regex, content, index=1):
search_result = '0'
search = re.compile(regex)
message = search.search(content)
if message:
if index == -1:
search_result = message.groups()
else:
search_result = message.groups(index)
return search_result[0]
# 生成债权
def create_loan(days, year_rate, period, money, area):
save_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "../test_file/loan.xlsx"))
incoming_code = time.strftime("%Y%m%d%H%M%S", time.localtime())
sn = incoming_code[4:]
wb = load_workbook(filename=save_path)
ws = wb['Sheet1']
ws['A2'] = sn
ws['C2'] = 'TS-A-' + sn
ws['H2'] = incoming_code
ws['E2'] = money
ws['AT2'] = area
now = datetime.datetime.now()
delta = datetime.timedelta(days=days)
loan_plan = now + delta
ws['N2'] = loan_plan.strftime('%Y/%m/%d')
ws['L2'] = year_rate
ws['J2'] = period
wb.save(save_path)
wb.close()
return 'TS-A-' + sn
# 导出进件后,添加出借人信息等并保存
def update_entry():
save_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "../TestFile/a.xlsx"))
contract_code = "HT"+time.strftime("%Y%m%d%H%M%S", time.localtime())
wb = load_workbook(filename=save_path)
ws = wb['导出进件总表']
ws['R2'] = "张某某"
ws['V2'] = contract_code
ws['W2'] = time.strftime("%Y/%m/%d", time.localtime())
ws['X2'] = "18920196666"
ws['Y2'] = "中国银行"
ws['Z2'] = "收款银行明细什么鬼"
ws['AA2'] = "6222019888888"
ws['AB2'] = "中国银行"
ws['AC2'] = "中国银行"
ws['AD2'] = "110228198902260370"
wb.save(save_path)
wb.close()
return contract_code
def copy_file(src_file, dst_file):
if os.path.isfile(dst_file):
os.remove(dst_file) # 先删除已有的文件
if not os.path.isfile(src_file):
print("%s not exist!" % src_file)
else:
f_path, f_name = os.path.split(dst_file) # 分离文件名和路径
if not os.path.exists(f_path):
os.makedirs(f_name) # 创建路径
shutil.copyfile(src_file, dst_file) # 复制文件
def findall(reg, content):
m = re.findall(reg, content)
return m
def timstamp():
a =str(int(time.time() * 1000))
return a
if __name__ == '__main__':
print("test here")
自动不重复生成身份证信息及生日,每天最多999个
from datetime import date
from config.config import *
import random
parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
districtcode_file = parent_dir + "/common/districtcode.txt"
def getdistrictcode():
codelist = []
codecity = []
file = open(districtcode_file,"r",encoding="utf-8")
lines = file.readlines() # 逐行读取
for line in lines:
if line.lstrip().rstrip().strip() != '' and (line.lstrip().rstrip().strip())[:6][-2:] != '00':
# 如果每行中去重后不为空,并且6位数字中最后两位不为00,则添加到列表里。(最后两位为00时为省份或地级市代码)
codelist.append(line[:6])
codecity.append(line[10:])
return codelist,codecity
def gennerator():
da = date.today()
codelist = getdistrictcode()[0]
id = codelist[random.randint(0, len(codelist))] # 地区项
year = str(int(da.strftime('%Y'))-24)
id = id + year
id = id + da.strftime('%m%d')
if da.strftime('%m%d') != get_var("date"):
set_var("date", da.strftime('%m%d'))
set_var("sequence", "1")
else:
set_var("sequence", str(int(get_var("sequence"))+1))
sequence = "%03d" % int(get_var("sequence"))
id = id + sequence # ,顺序号简单处理
i = 0
count = 0
weight = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2] # 权重项
checkcode = {'0': '1', '1': '0', '2': 'X', '3': '9', '4': '8', '5': '7', '6': '6', '7': '5', '8': '5', '9': '3',
'10': '2'} # 校验码映射
for i in range(0, len(id)):
count = count + int(id[i]) * weight[i]
id = id + checkcode[str(count % 11)] # 算出校验码
birthDate = da.strftime('%Y-%m-%d')
return id,birthDate
if __name__ == '__main__':
a = gennerator()
print(a[0],a[1])
print(parent_dir)
config 获取配置变量或者修改变量存储以待使用(参数化及关联一体化)
from configobj import ConfigObj
import os
cur_path = os.path.dirname(os.path.realpath(__file__))
configPath = os.path.join(cur_path, "config.ini")
cf = ConfigObj(configPath, encoding="UTF8")
def get_var(key, session="var"):
var = cf[session][key]
return var
def set_var(key, value, session="var"):
cf[session][key]=value
cf.write()
# cf.write(open(configPath, "r+", encoding="utf-8"))
if __name__ == '__main__':
print(get_var("productNo"), type(get_var("productNo")))
Project 项目api封装实例
from common import api_common, tool
from config.config import *
parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
zong_he_ye_wu = api_common.ReadExcel(parent_dir + "/TestFile/hyzh.xlsx", "zong_he_ye_wu") # 综合业务
class ZH(object):
# 用户系统登录,需要提供用户名和密码
def login(self, user_account, pwd):
request_demo = zong_he_ye_wu.request_test(1, user_account, pwd).post(None)
set_var("zh_session", str(request_demo["result_session"])) # 登录成功后,记住session
if __name__ == '__main__':
zh = ZH()
zh.login("admin", "123456")
TC 用unittest组织不同场景的测试用例
TestFile中Excel表格模版
TestReport生成的保存存储的地方
以上功能实现了,接口流程用例执行及邮件抄送执行报告