结构介绍
先来看下大体结构:
1、总体结构
2、细分结构
2.1、conf(全局变量)
2.2、cases(测试用例)
2.3、日志和报告
2.4、tools(通用工具模块)
2.5、core (代码模块)
2.6、bin(执行模块)
2.7、api_verify(单接口测试模块)
模块介绍
1、conf(全局变量)
所有得通用得变量都可以放在这里面,代码如下,大家一看就明白,不用多说了。
# -*- coding:utf-8 -*-
"""
全局变量
"""
import os
BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
LOG_PATH = os.path.join(BASE_PATH, 'logs') # log的路径
REPORT_PATH = os.path.join(BASE_PATH, 'report') # 报告的路径
CASE_PATH = os.path.join(BASE_PATH, 'cases') # 用例的存放路径
CORE_CASE_PATH = os.path.join(BASE_PATH, 'bin') # 生成的用例的存放路径
CORE_CASE_PATH1 = os.path.join(BASE_PATH, 'api_verify') # 生成的用例的存放路径
FILE_PATH = os.path.join(BASE_PATH,'core')
SFZ_PATH = os.path.join(BASE_PATH,'tools')
PHONENUMBER = '18500000020'
OLDPHONENUMBER = '18601337379'
PAYMENTPASSWORD1 ='111111'
PACKAGENAME = 'com.laijin.simplefinance'
USERAGENT = 'Mozilla/5.0 (Linux; U; Android 8.1.0; zh-cn; PACM00 Build/O11019) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30'
SCHEME = 'http'
SCHEME_s = 'https'
CREDITCARD_IDNO = 110101198501010076
# 信用卡绑卡身份证号
CREDITCARD_NO = 6225757520003932
# 信用卡卡号
# HOST = '10.103.27.11:8081'
API_HOSTS = {
'test1':'qa-api.jilc.com',
'test2':'qb-api.jilc.com',
'test3':'qc-api.jilc.com',
'test4':'qd-api.jilc.com',
'snb_test':'10.113.20.23:8080'
}
HOST = 'qa-api.jilc.com'
mysql_envs={
'test1':{
'HOST':'10.108.27.14',
'modify_zk_port':'9002',
'db':{
'PORT':3306,
'MYSQLDB':'test1_product',
'MYSQLUSER':'root',
'MYSQLPASSWORD':'123123'
}
},
'test2':{
'HOST':'10.108.27.14',
'modify_zk_port':'9003',
'db':{
'PORT':3306,
'MYSQLDB':'test2_product',
'MYSQLUSER':'root',
'MYSQLPASSWORD':'123123'
}
},
'test3':{
'HOST':'10.108.27.14',
'modify_zk_port':'9004',
'db':{
'PORT':3306,
'MYSQLDB':'test3_product',
'MYSQLUSER':'root',
'MYSQLPASSWORD':'123123'
}
},
'test4':{
'HOST':'10.108.27.14',
'modify_zk_port':'9005',
'db':{
'PORT':3306,
'MYSQLDB':'test4_product',
'MYSQLUSER':'root',
'MYSQLPASSWORD':'123123'
}
},
'snb_test':{
'HOST':'10.108.27.14',
'modify_zk_port':'8080',
'db':{
'PORT':3306,
'MYSQLDB':'dev1_fund',
'MYSQLUSER':'root',
'MYSQLPASSWORD':'123123'
}
}
}
ATHCODE ='123456'
LoginPassWord = 'abcd1234'
FALSEATHCODE = '654321'
SIGNKEY ='qwrobxkjlertty12edwsvfc@22#%^db'
BANKCARDPRENUM ='6225880155896666665'
# BANKCARDPRENUM ='622848'
PAYMENTPASSWORD ='123456'
CREDIT_CARD_NUMBER ='552599'
BANKSIMPLECODE_NYYH ='CMB'
BANKSIMPLECODE_HXYH ='HXB'
BANK_ID ='101'
BANK_NAME ='招商银行'
BANK_NAME_HXYY ='华夏银行'
WRONG_CARD_NUM ='622588015589666666'
AESKEY ='xvX7%l[K*lBRRX7!'
AESIV ='3293952646531178'
BANK_CARD_ROUTE_CHANNEL = 5
# 3:民生。5:通付盾
MAXWITHDRAWAMOUNT = 50000
1.2、cases(测试用例)
当然,代码里面得很多得配置都可以拿到表格中配置,比如:接口名称,参数等。
但是排列不能乱,需要对应取值得。
ID | 用例编号 | 版本 | 模块 | 功能 | 前提条件 | 操作步骤 | 预期结果 | 调用方法 |
1 | snb_Entrance_1 | 拾年宝 | 拾年宝入口 | 拾年宝入口是否正常 | 拾年宝入口进入 | 正常进入 | 正常进入 | self.base.snb_list_Entrance |
2 | snb_FrontPage_1 | 拾年宝 | 拾年宝首页 | 拾年宝首页是否正常 | 进入到拾年宝首页 | 正常进入 | 显示正常 | self.base.snb_front_page |
3 | snd_register_1 | 拾年宝 | 注册 | 注册功能是否正常 | 未注册的手机号 | 1.输入手机号,点击注册 2.输入验证码,点击注册 | 注册成功 | self.base.snd_register |
1.3、日志和报告
打印日志和存放报告得地方
日志:
可以根据自己得需求,添加或者减少打印信息
报告:
同样,可以根据自己得需求,添加或者减少生成的报告的信息
1.4、tools(通用工具模块)
通用的工具函数可以放在这里
比如连接数据库的:
class OpMysql(object):
def __init__(self,host, users, password, port, db):
self.host=host
self.users=users
self.password = password
self.port=port
self.db=db
def connect_mysql(self):
try:
conn = pymysql.connect(host=self.host, user=self.users, password=self.password, port=self.port,
db=self.db, charset='utf8')
conn._write_timeout = 10000
# cursor = conn.cursor()
return conn
except Exception as e:
w.write_log('数据库连接错误' + str(e))
def close_mysql(self):
conn= self.connect_mysql()
cursor = conn.cursor()
cursor.close()
conn.close()
def op_db_delete(self,sql):
conn = self.connect_mysql()
cursor = conn.cursor()
try:
print ('delsql',sql)
cursor.execute(sql)
except Exception as e:
w.write_log('sql异常' + str(e))
return e
else:
conn.commit()
res='数据库删除成功'
print ('数据库删除成功')
return res
def op_db_select(self,sql):
conn = self.connect_mysql()
cursor = conn.cursor()
try:
print (sql)
cursor.execute(sql)
except Exception as e:
w.write_log('sql异常' + str(e))
return e
else:
res_list = []
sql_res = cursor.fetchall()
print ('数据库查询成功')
# self.conn.cursor(0) #移动游标
for c in sql_res:
res_list.append(c)
return res_list
def op_db_update(self,sql):
# self.cursor = self.conn.cursor()
conn = self.connect_mysql()
cursor = conn.cursor()
try:
print ('update sql...',sql)
cursor.execute(sql)
except Exception as e:
w.write_log('sql异常' + str(e))
return e
else:
conn.commit()
res = '数据库修改成功'
print ('数据库修改成功')
return res
def op_db_insert(self,sql):
conn = self.connect_mysql()
cursor = conn.cursor()
try:
print ('update sql...', sql)
cursor.execute(sql)
except Exception as e:
w.write_log('sql异常' + str(e))
return e
else:
conn.commit()
res = '数据库添加成功'
print ('数据库添加成功')
return res
又比如自动生成手机号和RSA加密的:
class General_Tools(object):
def createphones(self):
prelist = ["130", "131", "132", "133", "134", "135", "136", "137", "138", "139", "147", "150", "151", "152",
"153", "155", "156", "157", "158", "159", "186", "187", "188"]
return random.choice(prelist) + "".join(random.choice("0123456789") for i in range(8))
def rsanumber(self, tokenkey):
"""rsa加密"""
url = 'http://10.107.24.198:5088/?method=rsaNumber&token=%s' % tokenkey
response = urllib2.urlopen(url)
html = response.read()
print (html)
return html
这里就不过多的介绍了
1.5、core (代码模块)
这个是重点,需要详细介绍的。
1.5.1、api_request.py
get请求:
class ApiRequest(object):
def __init__(self,api_host):#等进行实例化的时候,传入api_host
self.api_host=api_host
"""
定义函数 需要传入api和params两个参数
api举例就是host后面的内容,比如:/user/regOrLoginSms/verify
params就是指的参数了
"""
def get_api_request(self,api,params,scheme=SCHEME):
"""get请求接口"""
url = "%s://%s%s" % (scheme, self.api_host, api)#url由三部分组成,http或者https,host,api
headers = {"Content-Type": "application/gzip+encrypt+json",
"Accept-Encoding": "gzip",
"User-Agent": "Android_jianlicai"
}
r = requests.get(url,params,headers=headers,verify=False,timeout=10)#requests模块的get方法,timeout是超时时间,单位是秒
requests.adapters.DEFAULT_RETRIES = 10#设置重新连接的次数,大于会报错
if r.status_code==200: #获取响应的状态码
data = json.dumps(r.json(), ensure_ascii=False)
# 响应回来的是<dict>
# <dict>和<json>之间的转换
# <json> = json.dumps(<dict>)
# <dict> = json.loads(<json>)
return data
else:
w.write_log('服务器状态有误' + '状态码:' + str(r.status_code))#写log
post请求:和get不同的是requests的方法不同,用到的是requests.post
def post_api_request(self,api,params,scheme=SCHEME):
"""post请求接口"""
url="%s://%s%s"%(scheme,self.api_host,api)
headers = {"Content-Type": "application/json",
# headers = {"Content-Type": "application/json",
"Accept-Encoding": "gzip",
"User-Agent": STATISTICS
}
try:
r = requests.post(url, data=json.dumps(params), headers=headers, verify=False, timeout=100)
except Exception as e:
print e
w.write_log('异常情况:' + str(e))
return '不通过'
else:
requests.adapters.DEFAULT_RETRIES = 10
if r.status_code==200:
try:
data=json.dumps(r.json(),ensure_ascii=False)
except Exception as e:
w.write_log('异常情况:' + str(e))
else:
return data
else:
w.write_log('服务器状态有误'+'状态码:'+str(r.status_code))
1.5.2、base_api_request.py
此模块主要是编写出所有的接口。
这个是重中之重,详细介绍。
在这里拿注册功能,包括三个接口做下说明:
1.输入手机号码点击注册,接口名称:snb_regOrLoginSms_Get
2.输入手机验证码点击注册,接口名称:snb_regOrLoginSms_verify
3.设置登录密码,接口名称:/user/confirmPassword/toRegister
class BaseApiRequest(object):
"""开始编写所有的接口"""
def __init__(self, op_mysql, api_request):#实例化的时候传入op_mysql,api_request
self.op_mysql = op_mysql
self.api_request = api_request
def snb_regOrLoginSms_Get(self):
"""注册界面,输入手机号,点击注册按钮"""
"""正常接口参数"""
name = "注册界面,输入手机号,点击注册按钮"
api_url = '/user/regOrLoginSms/Get'
phonenumber = general_tools.createphones()#用到前面提到的生成手机号码的工具函数
params = {"userPhone": phonenumber, "type": 0}
"""接口返回值"""
response_json_data = self.api_request.post_api_request(api_url,params)
response_json_data = json.loads(response_json_data)#将返回的json转换成字典,用于后面在字典中的取值
"""判断接口正常状态"""
api_status, error = general_tools.check_response(name, response_json_data, 0)#调用前面提到的判断接口状态的函数
print ("接口名:%s,接口描述:%s,error值:%s,状态:%s" % (api_url, name, error, api_status))
return name, api_url, params, error, api_status, response_json_data,phonenumber#这里的phonenumber用于下一个接口使用
def snb_regOrLoginSms_verify(self,phonenumber):#phonenumber用到上一个接口返回的手机号码
"""注册界面,输入验证码,点击注册按钮"""
"""正常接口参数"""
name = "注册界面,输入验证码,点击注册按钮"
api_url = '/user/regOrLoginSms/verify'
params = {"userPhone":phonenumber,"smsCode":ATHCODE,"type":0,"wxopenId":"","source":""}#smsCode是在全局变量中配置的短信验证码
"""接口返回值"""
response_json_data = self.api_request.post_api_request(api_url,params)
response_json_data = json.loads(response_json_data)
userId= response_json_data["data"]["userId"]#从返回值中取出来,用于下一个函数
token = response_json_data["data"]["token"]#从返回值中取出来,用于下一个函数
"""判断接口正常状态"""
api_status, error = general_tools.check_response(name, response_json_data, 0)
print ("接口名:%s,接口描述:%s,error值:%s,状态:%s" % (api_url,name, error, api_status))
return name, api_url, params, error, api_status, response_json_data,userId,token#返回userId,token用于下一个接口使用
def snb_confirmPassword_toRegister(self,userId,token):
"""注册,设置登陆密码"""
"""正常接口参数"""
name = "注册界面,输入验证码,点击注册按钮"
api_url = '/user/confirmPassword/toRegister'
params = {"userId":userId,"token":token,"smsToken":"","loginPassWord":LoginPassWord,"repeatLoginPassWord":LoginPassWord,"type":0}
"""接口返回值"""
response_json_data = self.api_request.post_api_request(api_url,params)
response_json_data = json.loads(response_json_data)
"""判断接口正常状态"""
api_status, error = general_tools.check_response(name, response_json_data, 0)
print ("接口名:%s,接口描述:%s,error值:%s,状态:%s" % (api_url,name, error, api_status))
return name, api_url, params, error, api_status, response_json_data
1.5.3、flowcase.py
此模块的主要功能是把base_api_request.py模块的功能,组合起来,形成测试用例。这里面的用例只包含正常的逻辑。也就是说所有的接口的参数都是正常值,不包含非正常值的测试。那么问题来了,为什么要单独测试那?因为如果全部放在flowcase.py中测试,代码量会很多,不好维护;对于接口的非正常值得处理怎么测试那?后面会讲到。
重中之更重!!!
class Flowcase_Function(object):
def __init__(self, op_mysql, base_api_request, api_request, modify_zk_port):
self.op_mysql = op_mysql
self.base_api_request = BaseApiRequest(op_mysql,api_request)
self.api_request = api_request
self.modify_zk_port = modify_zk_port
print 'run.......'
"""主要流程"""
def snd_register(self, *args):#命名注册函数,用于测试注册相关的接口
"""注册"""
case_id = args[0]
detail = args[4]
project = args[2]
caseSummary = args[4]
model = args[3]
#上面这些变量在后面的时候会明白,就是获取的生成的测试用例中的变量
name,api_url,params,error,api_status,response_json_data,phonenumber = self.base_api_request.snb_regOrLoginSms_Get()#注册相关的第一个接口,并把返回值赋值给变量
name,api_url,params,error,api_status,response_json_data,userId,token = self.base_api_request.snb_regOrLoginSms_verify(phonenumber)#注册相关的第二个接口,并把返回值赋值给变量
name,api_url,params,error,api_status,response_json_data = self.base_api_request.snb_confirmPassword_toRegister(userId,token)#注册相关的第三个接口,并把返回值赋值给变量
#接口名称,接口URL,参数,error值,接口是否通过,接口返回信息
if api_status == '通过':
w.write_log(api_url + '\t' + '用例验证通过.' + name + '\n')
my_sql_result = ''
status = "通过"
dic_case = general_tools.op_reseponse_data(api_url, params, case_id,response_json_data,detail,my_sql_result, status,project,caseSummary,model)#op_reseponse_data函数看下面的代码
return dic_case #返回值主要用于生成测试报告使用
else:
# 返回值为空的时候
w.write_log(api_url + '\t' + '用例验证未通过!' + name + '\n')
my_sql_result = json.dumps(response_json_data, ensure_ascii=False)
status = "不通过"
dic_case = general_tools.op_reseponse_data(api_url, params, case_id,response_json_data,detail,my_sql_result, status,project,caseSummary,model)
return dic_case
下面分析下上面说的op_reseponse_data函数:
def op_reseponse_data(self,api_url,params,case_id,response_json_data, detail,status="不通过",my_sql_result='',*args):
res_list1 = []
report_dic1 = {
"url": api_url,
"request": params,
"response": response_json_data
}
res_list1.append(report_dic1)
print (res_list1)
dic_case = {
"case_id": case_id,
"project": args[0],#*agr上面函数传入的三个参数project,caseSummary,model取值
"model": args[-1],
"detail": args[2],
"caseSummary": args[-2],
"my_sql_result":status,
"status": my_sql_result ,
"responseDetial": res_list1
}
return dic_case
1.5.4、create_case.py
用于通过读取用例表格形成测试用例描述文件。
class GenCasePy(object):
def __init__(self, case_file, case_name):
'''
:param case_file: excel文件名
:param case_name: 生成的文件名,例如Case_reg
'''
self.case_file = case_file
self.case_name = case_name
def create_case_file(self):
"""读取excel,形成测试用例"""
book = xlrd.open_workbook(self.case_file)#打开文件
sheet = book.sheet_by_index(0)#第一个sheet
all_case = [] # 存放所有用例
for line in range(1,sheet.nrows):#读行 sheet.nrows
case = {} # 每条用例
temp = sheet.row_values(line)#获取每行的内容,形成列表,为下面的取值准备
case['ID'] = int(temp[0])
case['case_id'] = temp[1].encode('utf-8')
case['app_version'] = temp[2].encode('utf-8')
case['title'] = temp[3].encode('utf-8')
case['detail'] = temp[4].encode('utf-8')
case['def']=temp[8].encode('utf-8')
case['step'] = temp[6].encode('utf-8').replace('\n', '')
all_case.append(case)#读一行加一行
return all_case
def create_py_file(self):
"""把测试用例写进文件,形成一个py文件,一个测试用例代表一个函数"""
all_case_fun = '''
#coding=utf-8
import os,sys
reload(sys)
sys.setdefaultencoding('utf-8')
class %s(object):
def __init__(self,base):
self.base=base
''' % self.case_name
all_case = self.create_case_file()
for case in all_case:
case_fun = '''
def {case_id}(self,*arg,**kwargs):
ID = "{ID}"
case_id = "{case_id}"
app_version = "{app_version}"
title = "{title}"
detail = "{detail}"
step = "{step}"
return {def}(ID,case_id,app_version,title,detail,step)
'''.format(**case)
all_case_fun += case_fun
fw = open(CORE_CASE_PATH +'/'+ self.case_name + '.py', 'w')
fw.write(all_case_fun)
case_pyfile = GenCasePy(os.path.join(CASE_PATH, 'TestCase.xlsx'), 'snb_case')
case_pyfile.create_py_file()
运行上面的代码,会生成snb_case.py文件,内容如下:
class snb_case(object):
def __init__(self,base):
self.base=base
def snd_register_1(self,*arg,**kwargs):
ID = "3"
case_id = "snd_register_1"
app_version = "拾年宝"
title = "注册"
detail = "注册功能是否正常"
step = "1.输入手机号,点击注册2.输入验证码,点击注册"
return self.base.snd_register(ID,case_id,app_version,title,detail,step)
#调用flowcase.py中snb_register函数返回用例测试数据
到此为止,用例写完了,要执行用例了。
1.6、bin(执行模块)
1.6.1、snb_start.py
前面我们讲了各个部分,但是在这里,在这个执行文件中,才会真正得把流程得顺序和需要传入得参数都表示出来。把这个看明白了,自然也就会理解上面得那些模块了。因为这里用到了上面所有得模块。
import sys, os,socket,time
# from core.flowcase import base
base_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(base_path)
reload(sys)
sys.setdefaultencoding('utf-8')
from core.create_case import case_pyfile
from core.snb_report import HtmlReport
from tools.tools import OpMysql
from core.flowcase import Flowcase_Function
from core.base_api_request import BaseApiRequest
from conf import settings
from core.api_request import ApiRequest
from core.sendmail import SendMail
#判断是否是在本地运行,如果在本地运行,选择test1
if socket.gethostname().startswith('DESKTOP'):#判断是不是在我本机上执行得,如果是就获取固定得api_host和数据库对应的相关的信息
env='snb_test'
version='拾年宝'
api_host=settings.API_HOSTS.get(env)#获取host
# settings.HOST = settings.HOSTS.get(env)
host = settings.mysql_envs.get(env).get('HOST')#获取host获取数据的IP地址
#获取数据库的信息
users = settings.mysql_envs.get(env).get('db').get('MYSQLUSER')
password = settings.mysql_envs.get(env).get('db').get('MYSQLPASSWORD')
port = settings.mysql_envs.get(env).get('db').get('PORT')
db = settings.mysql_envs.get(env).get('db').get('MYSQLDB')
modify_zk_port=settings.mysql_envs.get(env).get('modify_zk_port')
#modify_zk_root = settings.mysql_envs.get(env).get('modify_zk_root')
else:
#执行start.py的时间,后面需要跟一个参数,这个参数是test*,从而获取到测试环境
#执行的时候的命令是在交互模式下,输入命令:python snb_start.py test1,则argv[1]对应的就是测试1的环境,就获取到测试1的api_host和数据库对应的相关的信息
env = sys.argv[1]
# test1,test2,test3,test4
api_host=settings.API_HOSTS.get(env)
host=settings.mysql_envs.get(env).get('HOST')
users=settings.mysql_envs.get(env).get('db').get('MYSQLUSER')
password=settings.mysql_envs.get(env).get('db').get('MYSQLPASSWORD')
port = settings.mysql_envs.get(env).get('db').get('PORT')
db = settings.mysql_envs.get(env).get('db').get('MYSQLDB')
modify_zk_port=settings.mysql_envs.get(env).get('modify_zk_port')
modify_zk_root = settings.mysql_envs.get(env).get('modify_zk_root')
version = sys.argv[2]#同上,执行start.py的时间,后面第二个参数,也就是版本信息
# op_mysql = OpMysql(host,users,password,db,port)
op_mysql = OpMysql(host,users,password,port,db) #连接数据库的
case_pyfile.create_py_file()#生成测试用例的.py文件
from snb_case import snb_case
api_request=ApiRequest(api_host)#实例化ApiRequest类
base_api_request = BaseApiRequest(op_mysql,api_request)#实例化baseApiRequest类
start_time=time.time()
if version=='拾年宝':
basecase = Flowcase_Function(op_mysql, base_api_request, api_request, modify_zk_port)#测试用例实例化
base_reg = snb_case(basecase)#生成的测试用例实例化 basecase == base
case_1 = base_reg.snb_Entrance_1()
case_2 = base_reg.snb_FrontPage_1()
case_3 = base_reg.snd_register_1()
#生成报告信息
case_list = []
case_list.append(case_1)
case_list.append(case_2)
case_list.append(case_3)
end_time=time.time()
# 以下是生成的报告内容
op_mysql.close_mysql()
# 关闭数据库
all = {}
total = len(case_list)
all['all']=total #用例总数
pass_count = 0 #通过的次数
for r in case_list:
if r['status']=='通过':
pass_count+=1
all['ok'] = pass_count#通过的次数
all['fail'] = total-pass_count#失败的次数
all['run_time'] = end_time-start_time
all['case_res']=case_list
report = HtmlReport(all)#实例化产生html类的对象
html_name = report.report()#调用生成html的方法,它返回报告的名字
title = time.strftime('%Y%m%d%H%M%S') + '接口测试报告'
content = '本次运行%s条用例,通过%s条,失败%s条。'%(total,pass_count,total-pass_count)
至此,就完成了,上面说过,至于单接口的测试(异常情况的测试怎么进行),下面就开始说。
1.7、api_verify(单接口全覆盖测试)
和上面的测试用例一样,会共用api_request.py模块,setting.py模块。
1.7.1、base_api_request_single_verify.py
def snb_regOrLoginSms_Get(self,*args):
"""注册界面,输入手机号,点击注册按钮"""
case_id = args[1]
detail = args[4]
project = args[2]
caseSummary = args[5]
model = args[3]
i = args[6] #取值index
name = "注册界面,输入手机号,点击注册按钮"
api_url = '/user/regOrLoginSms/Get'
phonenumber = general_tools.createphones()
#用列表的形式,列出所有的参数的组合
params = [{"userPhone": phonenumber, "type": 0},{"userPhone": "1500103256", "type": 0},{"userPhone": phonenumber, "type": 1}]
"""根据接口开发的定义自行进行判断"""
if i == 0:
except_error_code = 0
response_json_data = self.api_request.post_api_request(api_url,params[i])
response_json_data = json.loads(response_json_data)
elif i == 1:
except_error_code = 10003
response_json_data = self.api_request.post_api_request(api_url, params[i])
response_json_data = json.loads(response_json_data)
elif i == 2:
except_error_code = 100117
response_json_data = self.api_request.post_api_request(api_url, params[i])
response_json_data = json.loads(response_json_data)
"""判断接口状态"""
api_status, error = general_tools.check_response(name, response_json_data, except_error_code)
print ("接口名:%s,用例ID:%s,接口描述:%s,error值:%s,状态:%s" % (api_url,case_id, name, error, api_status))
if api_status == '通过':
w.write_log(case_id + '\t' + '接口验证通过.' + name + '\n')
my_sql_result = ''
status = "通过"
dic_case = general_tools.op_reseponse_data(api_url, params[i], case_id,response_json_data,detail,my_sql_result, status,project,caseSummary,model)
return dic_case
else:
# 返回值为空的时候
w.write_log(case_id + '\t' + '接口验证未通过!' + name + '\n')
my_sql_result = json.dumps(response_json_data, ensure_ascii=False)
status = "不通过"
dic_case = general_tools.op_reseponse_data(api_url, params[i], case_id,response_json_data,detail,my_sql_result, status,project,caseSummary,model)
return dic_case
1.7.2、snb_start_single_verify.py
和测试用例的执行文件,大体相同,有些小的改动,去掉了flowcase.py模块,因为是通过单接口直接进行测试了,不需要再组成测试用例了。
这里就不做过多的解释了,理解了上面的测试用例执行的流程,就不难理解这个了。
import sys, os,socket,time
# from core.flowcase import base
base_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(base_path)
reload(sys)
sys.setdefaultencoding('utf-8')
from api_verify.create_case_single_verify import case_pyfile
from core.snb_single_report import HtmlReport
from tools.tools import OpMysql
from api_verify.base_api_request_single_verify import BaseApiRequestVerify
from conf import settings
from core.api_request import ApiRequest
from api_verify.snb_case_single_verify import snb_case_single_verify
from core.sendmail import SendMail
#判断是否是在本地运行,如果在本地运行,选择test1
if socket.gethostname().startswith('DESKTOP'):#DESKTOP
env='snb_test'
version='拾年宝'
api_host=settings.API_HOSTS.get(env)#获取host
# settings.HOST = settings.HOSTS.get(env)
host = settings.mysql_envs.get(env).get('HOST')#获取host获取数据的IP地址
#获取数据库的信息
users = settings.mysql_envs.get(env).get('db').get('MYSQLUSER')
password = settings.mysql_envs.get(env).get('db').get('MYSQLPASSWORD')
port = settings.mysql_envs.get(env).get('db').get('PORT')
db = settings.mysql_envs.get(env).get('db').get('MYSQLDB')
modify_zk_port=settings.mysql_envs.get(env).get('modify_zk_port')
#modify_zk_root = settings.mysql_envs.get(env).get('modify_zk_root')
else:
#执行start.py的时间,后面需要跟一个参数,这个参数是test*,从而获取到测试环境
env = sys.argv[1]
# test1,test2,test3,test4
api_host=settings.API_HOSTS.get(env)
host=settings.mysql_envs.get(env).get('HOST')
users=settings.mysql_envs.get(env).get('db').get('MYSQLUSER')
password=settings.mysql_envs.get(env).get('db').get('MYSQLPASSWORD')
port = settings.mysql_envs.get(env).get('db').get('PORT')
db = settings.mysql_envs.get(env).get('db').get('MYSQLDB')
modify_zk_port=settings.mysql_envs.get(env).get('modify_zk_port')
modify_zk_root = settings.mysql_envs.get(env).get('modify_zk_root')
version = sys.argv[2]#同上,执行start.py的时间,后面第二个参数,也就是版本信息
# op_mysql = OpMysql(host,users,password,db,port)
op_mysql = OpMysql(host,users,password,port,db) #连接数据库的
case_pyfile.create_py_file()#生成测试用例的.py文件
from api_verify.snb_case_single_verify import snb_case_single_verify
api_request=ApiRequest(api_host)#实例化ApiRequest类
base_api_request_verify = BaseApiRequestVerify(op_mysql,api_request)#实例化baseApiRequest类
#a = base_api_verify.snb_regOrLoginSms_Get(0)
start_time=time.time()
if version=='拾年宝':
#basecase = Base_Flow_Function(op_mysql, base_api, api_request, modify_zk_port)#测试用例实例化
base_reg = snb_case_single_verify(base_api_request_verify)#生成的测试用例实例化 base_api_request_verify == base
case_1 = base_reg.snb_regOrLoginSms_Get_0()
case_2 = base_reg.snb_regOrLoginSms_Get_1()
case_3 = base_reg.snb_regOrLoginSms_Get_2()
#生成报告信息
case_list = []
case_list.append(case_1)
case_list.append(case_2)
case_list.append(case_3)
end_time=time.time()
# 以下是生成的报告内容
op_mysql.close_mysql()
# 关闭数据库
all = {}
total = len(case_list)
all['all']=total #用例总数
pass_count = 0 #通过的次数
for r in case_list:
if r['status']=='通过':
pass_count+=1
all['ok'] = pass_count#通过的次数
all['fail'] = total - pass_count#失败的次数
all['run_time'] = end_time-start_time
all['case_res']=case_list
report = HtmlReport(all)#实例化产生html类的对象
html_name = report.report()#调用生成html的方法,它返回报告的名字
title = time.strftime('%Y%m%d%H%M%S') + '接口测试报告'
content = '本次运行%s条用例,通过%s条,失败%s条。'%(total,pass_count,total-pass_count)
1.8、单接口测试生成的报告