@@ -0,0 +1,2 @@ | |||
# Default ignored files | |||
/workspace.xml |
@@ -0,0 +1,6 @@ | |||
<component name="InspectionProjectProfileManager"> | |||
<settings> | |||
<option name="USE_PROJECT_PROFILE" value="false" /> | |||
<version value="1.0" /> | |||
</settings> | |||
</component> |
@@ -0,0 +1,15 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<module type="PYTHON_MODULE" version="4"> | |||
<component name="NewModuleRootManager"> | |||
<content url="file://$MODULE_DIR$" /> | |||
<orderEntry type="inheritedJdk" /> | |||
<orderEntry type="sourceFolder" forTests="false" /> | |||
</component> | |||
<component name="PyDocumentationSettings"> | |||
<option name="format" value="PLAIN" /> | |||
<option name="myDocStringFormat" value="Plain" /> | |||
</component> | |||
<component name="TestRunnerService"> | |||
<option name="PROJECT_TEST_RUNNER" value="pytest" /> | |||
</component> | |||
</module> |
@@ -0,0 +1,7 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<project version="4"> | |||
<component name="JavaScriptSettings"> | |||
<option name="languageLevel" value="ES6" /> | |||
</component> | |||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10" project-jdk-type="Python SDK" /> | |||
</project> |
@@ -0,0 +1,8 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<project version="4"> | |||
<component name="ProjectModuleManager"> | |||
<modules> | |||
<module fileurl="file://$PROJECT_DIR$/.idea/jiekou-python3.iml" filepath="$PROJECT_DIR$/.idea/jiekou-python3.iml" /> | |||
</modules> | |||
</component> | |||
</project> |
@@ -0,0 +1,6 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<project version="4"> | |||
<component name="VcsDirectoryMappings"> | |||
<mapping directory="$PROJECT_DIR$" vcs="Git" /> | |||
</component> | |||
</project> |
@@ -0,0 +1,29 @@ | |||
""" | |||
@author: lileilei | |||
@file: dubbo_feng.py | |||
@time: 2018/3/29 12:26 | |||
""" | |||
from pyhessian.client import HessianProxy | |||
from pyhessian import protocol | |||
from public.log import LOG, logger | |||
@logger('dubbo接口') | |||
class DubboInterface: | |||
def __init__(self, url, interface, method, param, **kwargs): | |||
self.url = url | |||
self.interface = interface | |||
self.method = method | |||
self.param = param | |||
self.interfaceparam = protocol.object_factory(self.param, **kwargs) | |||
def getresult(self): | |||
try: | |||
result = HessianProxy(self.url + self.interface) | |||
return_result = getattr(result, self.method)(self.interfaceparam) | |||
LOG.info('测试返回结果:%s' % return_result) | |||
res = {'code': 0, 'result': return_result} | |||
except Exception as e: | |||
LOG.info('测试失败,原因:%s' % e) | |||
res = {'code': 1, 'result': e} | |||
return res |
@@ -0,0 +1,29 @@ | |||
# -*- coding: utf-8 -*- | |||
# @Time : 2017/6/4 20:36 | |||
# @Author : lileilei | |||
# @Site : | |||
# @File : testFengzhuang.py | |||
from Public.test_requests import requ | |||
class TestApi(object): | |||
def __init__(self, url, parame, method): | |||
self.url = url | |||
self.parame = parame | |||
self.method = method | |||
self.reques = requ() | |||
def testapi(self): | |||
if self.method == 'POST': | |||
self.response = self.reques.post(self.url, self.parame) | |||
elif self.method == "GET": | |||
self.response = self.reques.get(url=self.url, params=self.parame) | |||
elif self.method == "PUT": | |||
self.response = self.reques.putparams(url=self.url, params=self.parame) | |||
elif self.method == "DELETE": | |||
self.response = self.reques.delparams(url=self.url, params=self.parame) | |||
return self.response | |||
def getJson(self): | |||
json_data = self.testapi() | |||
return json_data |
@@ -0,0 +1 @@ | |||
# -*- coding: utf-8 -*- # @Author : leizi import requests, json from public.log import LOG, logger @logger('requests封装') class requ(): def __init__(self): self.headers = { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:51.0) Gecko/20100101 Firefox/51.0"} def get(self, url): # get消息 try: r = requests.get(url, headers=self.headers) r.encoding = 'UTF-8' json_response = json.loads(r.text) return json_response except Exception as e: LOG.info('get请求出错,出错原因:%s' % e) print('get请求出错,出错原因:%s' % e) return {} def post(self, url, params): # post消息 data = json.dumps(params) try: r = requests.post(url, params=params, headers=self.headers) json_response = json.loads(r.text) return json_response except Exception as e: LOG.info('post请求出错,出错原因:%s' % e) print('post请求出错,原因:%s' % e) def delfile(self, url, params): # 删除的请求 try: del_word = requests.delete(url, params, headers=self.headers) json_response = json.loads(del_word.text) return json_response except Exception as e: LOG.info('del请求出错,出错原因:%s' % e) print('del请求出错,原因:%s' % e) return {} def putfile(self, url, params): # put请求 try: data = json.dumps(params) me = requests.put(url, data) json_response = json.loads(me.text) return json_response except Exception as e: LOG.info('put请求出错,出错原因:%s' % e) print('put请求出错,原因:%s' % e) return json_response |
@@ -0,0 +1,27 @@ | |||
""" | |||
@author: lileilei | |||
@file: Dingtalk.py | |||
@time: 2017/12/26 17:34 | |||
""" | |||
'''封装钉钉群发消息''' | |||
import requests, json | |||
from config.config import Dingtalk_access_token | |||
def send_ding(content): | |||
url = Dingtalk_access_token | |||
pagrem = { | |||
"msgtype": "text", | |||
"text": { | |||
"content": content | |||
}, | |||
"isAtAll": True | |||
} | |||
headers = { | |||
'Content-Type': 'application/json' | |||
} | |||
f = requests.post(url, data=json.dumps(pagrem), headers=headers) | |||
if f.status_code == 200: | |||
return True | |||
else: | |||
return False |
@@ -0,0 +1,6 @@ | |||
# -*- coding: utf-8 -*- | |||
# @Time : 2017/6/4 17:34 | |||
# @Author : lileilei | |||
# @Site : | |||
# @File : __init__.py.py | |||
# @Software: PyCharm |
@@ -0,0 +1,18 @@ | |||
# encoding: utf-8 | |||
""" | |||
@author: lileilei | |||
@file: create_report.py | |||
@time: 2017/8/3 12:27 | |||
""" | |||
from Public.log import LOG, logger | |||
@logger('保存测试结果') | |||
def save_result(testtime, toial, passnum, fail): | |||
try: | |||
f = open('result.txt', 'a') | |||
f.write("%s=%s=%s=%s \n" % (testtime, toial, passnum, fail)) | |||
f.close() | |||
except: | |||
LOG.info('保存测试结果出错,原因:%s' % Exception) | |||
print('记录测试结果失败') |
@@ -0,0 +1,35 @@ | |||
# -*- coding: utf-8 -*- | |||
# @Author : leizi | |||
import smtplib, time, os | |||
from email.mime.text import MIMEText | |||
from email.mime.multipart import MIMEMultipart | |||
import yaml | |||
def load_emil_setting(): # 从配置文件中加载获取email的相关信息 | |||
filepath = os.path.join(os.path.join(os.getcwd(), 'config'), 'email.yaml') | |||
data_file = open(filepath, "r") | |||
datas = yaml.load(data_file, Loader=yaml.FullLoader) | |||
data_file.close() | |||
return (datas['foremail'], datas['password'], datas['toeamil'], datas['title']) | |||
def sendemali(filepath): # 发送email | |||
from_addr, password, mail_to, mail_body = load_emil_setting() | |||
msg = MIMEMultipart() | |||
msg['Subject'] = '接口自动化测试报告' | |||
msg['From'] = '自动化测试平台' | |||
msg['To'] = mail_to | |||
msg['Date'] = time.strftime('%a, %d %b %Y %H:%M:%S %z') | |||
att = MIMEText(open(r'%s' % filepath, 'rb').read(), 'base64', 'utf-8') | |||
att["Content-Type"] = 'application/octet-stream' | |||
att["Content-Disposition"] = 'attachment; filename="pyresult.html"' | |||
txt = MIMEText("这是测试报告的邮件,详情见附件", 'plain', 'gb2312') | |||
msg.attach(txt) | |||
msg.attach(att) | |||
smtp = smtplib.SMTP() | |||
server = smtplib.SMTP_SSL("smtp.qq.com", 465) | |||
server.login(from_addr, password) | |||
server.sendmail(from_addr, mail_to, msg.as_string()) | |||
server.quit() |
@@ -0,0 +1,36 @@ | |||
""" | |||
@author: lileilei | |||
@file: python_dict.py | |||
@time: 2018/6/15 13:54 | |||
""" | |||
'''字典取值''' | |||
def res(d, code): | |||
result = [] | |||
if isinstance(d, dict) and code in d.keys(): | |||
value = d[code] | |||
result.append(value) | |||
return result | |||
elif isinstance(d, (list, tuple)): | |||
for item in d: | |||
value = res(item, code) | |||
if value == "None" or value is None: | |||
pass | |||
elif len(value) == 0: | |||
pass | |||
else: | |||
result.append(value) | |||
return result | |||
else: | |||
if isinstance(d, dict): | |||
for k in d: | |||
value = res(d[k], code) | |||
if value == "None" or value is None: | |||
pass | |||
elif len(value) == 0: | |||
pass | |||
else: | |||
for item in value: | |||
result.append(item) | |||
return result |
@@ -0,0 +1,50 @@ | |||
# -*- coding: utf-8 -*- | |||
# @Time : 2017/6/4 20:35 | |||
# @Author : lileilei | |||
# @File : get_excel.py | |||
import xlrd, os | |||
from Public.log import LOG, logger | |||
@logger('解析测试用例文件') | |||
def datacel(filepath): | |||
try: | |||
file = xlrd.open_workbook(filepath) | |||
print(file) | |||
rslut = file.sheets()[0] | |||
nrows = rslut.nrows | |||
listid = [] | |||
listkey = [] | |||
listconeent = [] | |||
listurl = [] | |||
listmethod = [] | |||
listassert = [] | |||
listname = [] | |||
for i in range(1, nrows): | |||
listid.append(rslut.cell(i, 0).value) | |||
listkey.append(rslut.cell(i, 2).value) | |||
listconeent.append(rslut.cell(i, 3).value) | |||
listurl.append(rslut.cell(i, 4).value) | |||
listname.append(rslut.cell(i, 1).value) | |||
listmethod.append((rslut.cell(i, 5).value)) | |||
listassert.append((rslut.cell(i, 6).value)) | |||
return listid, listkey, listconeent, listurl, listmethod, listassert, listname | |||
except Exception as e: | |||
print(e) | |||
LOG.info('打开测试用例失败,原因是:%s' % e) | |||
return | |||
@logger('生成数据驱动所用数据') | |||
def makedata(): | |||
path = os.path.join(os.path.join(os.getcwd(), 'test_case_data'), 'case.xlsx') | |||
listid, listkey, listconeent, listurl, listmethod, listassert, listname = datacel(path) | |||
make_data = [] | |||
for i in range(len(listid)): | |||
make_data.append({'url': listurl[i], 'key': listkey[i], | |||
'coneent': listconeent[i], 'method': listmethod[i], | |||
'assertconnect': listassert[i], | |||
'id': listid[i]}, | |||
) | |||
i += 1 | |||
return make_data |
@@ -0,0 +1,20 @@ | |||
""" | |||
@author: lileilei | |||
@file: get_excel_new.py | |||
@time: 2018/4/30 11:04 | |||
""" | |||
'''读取Excel''' | |||
import xlrd | |||
def datacel(filrpath): | |||
all_case = [] | |||
file = xlrd.open_workbook(filrpath) | |||
me = file.sheets()[0] | |||
nrows = me.nrows | |||
for i in range(1, nrows): | |||
all_case.append({"id": me.cell(i, 0).value, 'key': me.cell(i, 2).value, | |||
'coneent': me.cell(i, 3).value, 'url': me.cell(i, 4).value, | |||
'name': me.cell(i, 1).value, 'fangshi': me.cell(i, 5).value, | |||
'assert': me.cell(i, 6).value}) | |||
return all_case |
@@ -0,0 +1,47 @@ | |||
# -*- coding: utf-8 -*- | |||
# @Date : 2017-10-14 15:35:17 | |||
# @Author : leizi | |||
'''日志模块''' | |||
import os | |||
import logbook | |||
from logbook.more import ColorizedStderrHandler | |||
from functools import wraps | |||
check_path = '.' | |||
LOG_DIR = os.path.join(check_path, 'log') | |||
file_stream = False | |||
if not os.path.exists(LOG_DIR): | |||
os.makedirs(LOG_DIR) | |||
file_stream = True | |||
def get_logger(name='interface_case_run', file_log=file_stream, level=''): | |||
""" get logger Factory function """ | |||
logbook.set_datetime_format('local') | |||
ColorizedStderrHandler(bubble=False, level=level).push_thread() | |||
logbook.TimedRotatingFileHandler( | |||
os.path.join(LOG_DIR, '%s.log' % name), | |||
date_format='%Y_%m_%d_%H', bubble=True, encoding='utf-8').push_thread() | |||
return logbook.Logger(name) | |||
LOG = get_logger(file_log=file_stream, level='INFO') | |||
def logger(param): | |||
""" fcuntion from logger meta """ | |||
def wrap(function): | |||
""" logger wrapper """ | |||
@wraps(function) | |||
def _wrap(*args, **kwargs): | |||
""" wrap tool """ | |||
LOG.info("当前模块 {}".format(param)) | |||
LOG.info("全部args参数参数信息 , {}".format(str(args))) | |||
LOG.info("全部kwargs参数信息 , {}".format(str(kwargs))) | |||
return function(*args, **kwargs) | |||
return _wrap | |||
return wrap |
@@ -0,0 +1,32 @@ | |||
# -*- coding: utf-8 -*- | |||
# @Date : 2017-08-02 21:54:08 | |||
# @Author : lileilei | |||
from Public.fengzhuang_dict import res | |||
from .log import LOG, logger | |||
@logger('断言测试结果') | |||
def assert_in(asserassert, returnjson): | |||
if len(asserassert.split('=')) > 1: | |||
data = asserassert.split('&') | |||
result = dict([(item.split('=')) for item in data]) | |||
value1 = ([(str(res(returnjson, key))) for key in result.keys()]) | |||
value2 = ([(str(value)) for value in result.values()]) | |||
if value1 == value2: | |||
return {'code': 0, "result": 'pass'} | |||
else: | |||
return {'code': 1, 'result': 'fail'} | |||
else: | |||
LOG.info('填写测试预期值') | |||
return {"code": 2, 'result': '填写测试预期值'} | |||
@logger('断言测试结果') | |||
def assertre(asserassert): | |||
if len(asserassert.split('=')) > 1: | |||
data = asserassert.split('&') | |||
result = dict([(item.split('=')) for item in data]) | |||
return result | |||
else: | |||
LOG.info('填写测试预期值') | |||
raise {"code": 1, 'result': '填写测试预期值'} |
@@ -0,0 +1,180 @@ | |||
# encoding: utf-8 | |||
""" | |||
@author: lileilei | |||
@file: py_Html.py | |||
@time: 2017/6/5 17:04 | |||
""" | |||
titles = '接口测试' | |||
def title(titles): | |||
title = '''<!DOCTYPE html> | |||
<html> | |||
<head> | |||
<title>%s</title> | |||
<meta charset="UTF-8"> | |||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |||
<!-- 引入 Bootstrap --> | |||
<link href="https://cdn.bootcss.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"> | |||
<!-- HTML5 Shim 和 Respond.js 用于让 IE8 支持 HTML5元素和媒体查询 --> | |||
<!-- 注意: 如果通过 file:// 引入 Respond.js 文件,则该文件无法起效果 --> | |||
<!--[if lt IE 9]> | |||
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script> | |||
<script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script> | |||
<![endif]--> | |||
<style type="text/css"> | |||
.hidden-detail,.hidden-tr{ | |||
display:none; | |||
} | |||
</style> | |||
</head> | |||
<body> | |||
''' % (titles) | |||
return title | |||
connent = ''' | |||
<div class='col-md-4 col-md-offset-4' style='margin-left:3%;'> | |||
<h1>接口测试的结果</h1>''' | |||
def shouye(starttime, endtime, passge, fail, excepthions, weizhicuowu): | |||
beijing = ''' | |||
<table class="table table-hover table-condensed"> | |||
<tbody> | |||
<tr> | |||
<td><strong>开始时间:</strong> %s</td> | |||
</tr> | |||
<td><strong>结束时间:</strong> %s</td></tr> | |||
<td><strong>耗时:</strong> %s</td></tr> | |||
<td><strong>结果:</strong> | |||
<span >Pass: <strong >%s</strong> | |||
Fail: <strong >%s</strong> | |||
exception: <strong >%s</strong> | |||
weizhicuowu : <strong >%s</strong></span></td> | |||
</tr> | |||
</tbody></table> | |||
</div> ''' % (starttime, endtime, (endtime - starttime), passge, fail, excepthions, weizhicuowu) | |||
return beijing | |||
shanghai = '''<div class="row " style="margin:60px"> | |||
<div style=' margin-top: 18%;' > | |||
<div class="btn-group" role="group" aria-label="..."> | |||
<button type="button" id="check-all" class="btn btn-primary">所有用例</button> | |||
<button type="button" id="check-success" class="btn btn-success">成功用例</button> | |||
<button type="button" id="check-danger" class="btn btn-danger">失败用例</button> | |||
<button type="button" id="check-warning" class="btn btn-warning">错误用例</button> | |||
<button type="button" id="check-except" class="btn btn-defult">异常用例</button> | |||
</div> | |||
<div class="btn-group" role="group" aria-label="..."> | |||
</div> | |||
<table class="table table-hover table-condensed table-bordered" style="word-wrap:break-word; word-break:break-all; margin-top: 7px;"> | |||
<tr > | |||
<td ><strong>用例ID </strong></td> | |||
<td><strong>用例名字</strong></td> | |||
<td><strong>key</strong></td> | |||
<td><strong>请求内容</strong></td> | |||
<td><strong>url</strong></td> | |||
<td><strong>请求方式</strong></td> | |||
<td><strong>预期</strong></td> | |||
<td><strong>实际返回</strong></td> | |||
<td><strong>结果</strong></td> | |||
</tr> | |||
''' | |||
def passfail(tend): | |||
if tend == 'pass': | |||
htl = '''<td bgcolor="green">pass</td>''' | |||
elif tend == 'fail': | |||
htl = '''<td bgcolor="fail">fail</td>''' | |||
elif tend == 'weizhi': | |||
htl = '''<td bgcolor="red">error</td>''' | |||
else: | |||
htl = '<td bgcolor="crimson">exect</td>' | |||
return htl | |||
def ceshixiangqing(reslt, id, name, key, coneent, url, meth, yuqi, json, relust): | |||
xiangqing = ''' | |||
<tr class="case-tr %s"> | |||
<td>%s</td> | |||
<td>%s</td> | |||
<td>%s</td> | |||
<td>%s</td> | |||
<td>%s</td> | |||
<td>%s</td> | |||
<td>%s</td> | |||
<td>%s</td> | |||
%s | |||
</tr> | |||
''' % (reslt, id, name, key, coneent, url, meth, yuqi, json, passfail(relust)) | |||
return xiangqing | |||
weibu = '''</div></div></table><script src="https://code.jquery.com/jquery.js"></script> | |||
<script src="https://cdn.bootcss.com/bootstrap/3.3.6/js/bootstrap.min.js"></script> | |||
<script type="text/javascript"> | |||
$("#check-danger").click(function(e){ | |||
$(".case-tr").removeClass("hidden-tr"); | |||
$(".success").addClass("hidden-tr"); | |||
$(".warning").addClass("hidden-tr"); | |||
$(".error").addClass("hidden-tr"); | |||
}); | |||
$("#check-warning").click(function(e){ | |||
$(".case-tr").removeClass("hidden-tr"); | |||
$(".success").addClass("hidden-tr"); | |||
$(".danger").addClass("hidden-tr"); | |||
$(".error").addClass("hidden-tr"); | |||
}); | |||
$("#check-success").click(function(e){ | |||
$(".case-tr").removeClass("hidden-tr"); | |||
$(".warning").addClass("hidden-tr"); | |||
$(".danger").addClass("hidden-tr"); | |||
$(".error").addClass("hidden-tr"); | |||
}); | |||
$("#check-except").click(function(e){ | |||
$(".case-tr").removeClass("hidden-tr"); | |||
$(".warning").addClass("hidden-tr"); | |||
$(".danger").addClass("hidden-tr"); | |||
$(".success").addClass("hidden-tr"); | |||
}); | |||
$("#check-all").click(function(e){ | |||
$(".case-tr").removeClass("hidden-tr"); | |||
}); | |||
</script> | |||
</body></html>''' | |||
def relust(titles, starttime, endtime, passge, fail, id, name, key, coneent, url, meth, yuqi, json, relust, exceptions, | |||
weizhi): | |||
if type(name) == list: | |||
relus = ' ' | |||
for i in range(len(name)): | |||
if relust[i] == "pass": | |||
clazz = "success" | |||
elif relust[i] == "fail": | |||
clazz = "warning" | |||
elif relust[i] == "weizhi": | |||
clazz = "danger" | |||
else: | |||
clazz = 'error' | |||
relus += ( | |||
ceshixiangqing(clazz, id[i], name[i], key[i], coneent[i], url[i], meth[i], yuqi[i], json[i], relust[i])) | |||
text = title(titles) + connent + shouye(starttime, endtime, passge, fail, exceptions, | |||
weizhi) + shanghai + relus + weibu | |||
else: | |||
text = title(titles) + connent + shouye(starttime, endtime, passge, fail, exceptions, | |||
weizhi) + shanghai + ceshixiangqing(id, name, key, coneent, url, meth, | |||
yuqi, json, relust) + weibu | |||
return text | |||
def createHtml(filepath, titles, starttime, endtime, passge, fail, id, name, key, coneent, url, meth, yuqi, json, | |||
relusts, exceptions, weizhi): | |||
texts = relust(titles, starttime, endtime, passge, fail, id, name, key, coneent, url, meth, yuqi, json, relusts, | |||
exceptions, weizhi) | |||
with open(filepath, 'wb') as f: | |||
f.write(texts.encode('utf-8')) |
@@ -0,0 +1,113 @@ | |||
# encoding: utf-8 | |||
""" | |||
@author: lileilei | |||
@file: pyreport_excel.py | |||
@time: 2017/6/7 8:47 | |||
""" | |||
import os, xlwt, yaml | |||
from xlwt import * | |||
def yangshi1(): | |||
style = XFStyle() | |||
fnt = Font() | |||
fnt.name = u'微软雅黑' | |||
fnt.bold = True | |||
style.font = fnt | |||
alignment = xlwt.Alignment() | |||
alignment.horz = xlwt.Alignment.HORZ_CENTER | |||
alignment.vert = xlwt.Alignment.VERT_CENTER | |||
style.alignment = alignment # 给样式添加文字居中属性 | |||
style.font.height = 430 # 设置字体大小 | |||
return style | |||
def yangshi2(): | |||
style1 = XFStyle() | |||
alignment = xlwt.Alignment() | |||
alignment.horz = xlwt.Alignment.HORZ_CENTER | |||
alignment.vert = xlwt.Alignment.VERT_CENTER | |||
style1.alignment = alignment # 给样式添加文字居中属性 | |||
style1.font.height = 330 # 设置字体大小 | |||
return style1 | |||
def yangshi3(): | |||
style1 = XFStyle() | |||
style1.font.height = 330 # 设置字体大小 | |||
return style1 | |||
def yangshique(me): | |||
if me == 'pass': | |||
style = yangshi1() | |||
Pattern = xlwt.Pattern() | |||
Pattern.pattern = xlwt.Pattern.SOLID_PATTERN | |||
Pattern.pattern_fore_colour = xlwt.Style.colour_map['green'] | |||
style.pattern = Pattern | |||
else: | |||
style = yangshi2() | |||
Pattern = xlwt.Pattern() | |||
Pattern.pattern = xlwt.Pattern.SOLID_PATTERN | |||
Pattern.pattern_fore_colour = xlwt.Style.colour_map['red'] | |||
style.pattern = Pattern | |||
return style | |||
def create(filename, list_pass, list_fail, listids, listnames, listkeys, listconeents, listurls, listfangshis, | |||
listqiwangs, list_json, listrelust): | |||
filepath = open(os.path.join(os.path.join(os.getcwd(), 'config'), 'test_report.yaml'), encoding='utf-8') | |||
file_config = yaml.load(filepath, Loader=yaml.FullLoader) | |||
file = Workbook(filename) | |||
table = file.add_sheet('测试结果', cell_overwrite_ok=True) | |||
style = yangshi1() | |||
for i in range(0, 7): | |||
table.col(i).width = 380 * 20 | |||
style1 = yangshi2() | |||
table.write_merge(0, 0, 0, 6, '测试报告', style=style) | |||
table.write_merge(1, 1, 0, 6, '', style=style) | |||
table.write_merge(2, 3, 0, 6, '测试详情', style=style1) | |||
table.write(4, 0, '项目名称', style=style1) | |||
table.write(5, 0, '接口版本', style=style1) | |||
table.write(6, 0, '提测时间', style=style1) | |||
table.write(7, 0, '提测人', style=style1) | |||
table.write(4, 2, '测试人', style=style1) | |||
table.write(5, 2, '测试时间', style=style1) | |||
table.write(6, 2, '审核人', style=style1) | |||
table.write(4, 4, '通过', style=style1) | |||
table.write(5, 4, '失败', style=style1) | |||
table.write(6, 4, '成功率', style=style1) | |||
table.write(4, 1, (file_config['projectname']), style=style1) | |||
table.write(5, 1, file_config['interfaceVersion'], style=style1) | |||
table.write(6, 1, file_config['tijiao_time'], style=style1) | |||
table.write(7, 1, file_config['tijiao_person'], style=style1) | |||
table.write(4, 3, file_config['ceshi_person'], style=style1) | |||
table.write(5, 3, file_config['ceshi_time'], style=style1) | |||
table.write(6, 3, file_config['shenhename'], style=style1) | |||
table.write(4, 5, (list_pass), style=style1) | |||
table.write(5, 5, (list_fail), style=style1) | |||
table.write(6, 5, ('%.2f%%' % ((list_pass) / (len(listrelust)))), style=style1) | |||
table1 = file.add_sheet('测试详情', cell_overwrite_ok=True) | |||
table1.write_merge(0, 0, 0, 8, '测试详情', style=style) | |||
for i in range(0, 8): | |||
table1.col(i).width = 400 * 20 | |||
table1.write(1, 0, '用例ID', style=yangshi3()) | |||
table1.write(1, 1, '用例名字', style=yangshi3()) | |||
table1.write(1, 2, 'key', style=yangshi3()) | |||
table1.write(1, 3, '请求内容', style=yangshi3()) | |||
table1.write(1, 4, ' url', style=yangshi3()) | |||
table1.write(1, 5, '请求方式', style=yangshi3()) | |||
table1.write(1, 6, '预期', style=yangshi3()) | |||
table1.write(1, 7, '实际返回', style=yangshi3()) | |||
table1.write(1, 8, '结果', style=yangshi3()) | |||
for i in range(len(listids)): | |||
table1.write(i + 1, 0, listids[i], style=yangshi3()) | |||
table1.write(i + 1, 1, listnames[i], style=yangshi3()) | |||
table1.write(i + 1, 2, listkeys[i], style=yangshi3()) | |||
table1.write(i + 1, 3, listconeents[i], style=yangshi3()) | |||
table1.write(i + 1, 4, listurls[i], style=yangshi3()) | |||
table1.write(i + 1, 5, listfangshis[i], style=yangshi3()) | |||
table1.write(i + 1, 6, listqiwangs[i], style=yangshi3()) | |||
table1.write(i + 1, 7, str(list_json[i]), style=yangshi3()) | |||
table1.write(i + 1, 8, listrelust[i], style=yangshique(listrelust[i])) | |||
file.save(filename) |
@@ -0,0 +1 @@ | |||
# -*- coding: utf-8 -*- # @Author : leizi import requests, json from requests import Timeout, RequestException class requ(): def __init__(self): self.headers = { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:51.0) Gecko/20100101 Firefox/51.0"} def get(self, url, params): # get消息 try: r = requests.get(url, params=params, headers=self.headers) r.encoding = 'UTF-8' if r.status_code == 200: json_response = json.loads(r.text) return {'code': 0, 'result': json_response} else: return {'code': 1, 'result': '接口请求失败,返回状态码:%s' % str(r.status_code)} except Timeout as e: return {'code': 1, 'result': '请求超时:%s' % e} except RequestException as e: return {'code': 1, 'result': '请求异常:%s' % e} except Exception as e: return {'code': 1, 'result': 'get请求出错,出错原因:%s' % e} def post(self, url, params): # post消息 data = json.dumps(params) try: r = requests.post(url, params=data, headers=self.headers) if r.status_code == 200: json_response = json.loads(r.text) return {'code': 0, 'result': json_response} else: return {'code': 1, 'result': '接口请求失败,返回状态码:%s' % str(r.status_code)} except Timeout as e: return {'code': 1, 'result': '请求超时:%s' % e} except RequestException as e: return {'code': 1, 'result': '请求异常:%s' % e} except Exception as e: return {'code': 1, 'result': 'post请求出错,出错原因:%s' % e} def delparams(self, url, params): # 删除的请求 try: del_word = requests.delete(url, params=params, headers=self.headers) if del_word.status_code == 200: json_response = json.loads(del_word.text) return {'code': 0, 'result': json_response} else: return {'code': 1, 'result': '接口请求失败,返回状态码:%s' % str(del_word.status_code)} except Timeout as e: return {'code': 1, 'result': '请求超时:%s' % e} except RequestException as e: return {'code': 1, 'result': '请求异常:%s' % e} except Exception as e: return {'code': 1, 'result': 'del请求出错,出错原因:%s' % e} def putparams(self, url, params): # put请求 try: data = json.dumps(params) result = requests.put(url, data) if result.status_code == 200: json_response = json.loads(result.text) return {'code': 0, 'result': json_response} else: return {'code': 1, 'result': '接口请求失败,返回状态码:%s' % str(result.status_code)} except Timeout as e: return {'code': 1, 'result': '请求超时:%s' % e} except RequestException as e: return {'code': 1, 'result': '请求异常:%s' % e} except Exception as e: return {'code': 1, 'result': 'put请求出错,出错原因:%s' % e} |
@@ -0,0 +1,37 @@ | |||
# 接口测试框架(基于json格式、http请求,python3,不兼容python2.x版本) | |||
## 注:现在基于Excel文件管理测试用例基本实现,) | |||
## 备注:大家在运行的时候,如果参数不需要key,只需要字典,可以在ddt_case.py和case.py改造parame,注释掉现在的parem,启用新的即可 | |||
## 依赖用例支持用例执行,在testCase的ddt_case.py有实现,逻辑在代码中有写,参数的格式{"name":"$case1=data"}即代表name的值是case1的data字段,简单的实现。 | |||
## 依赖用例是简单的实现,具体在业务上面还有很多复杂的要处理,知识实现了,部分的思路。 | |||
## (目前在部分window上会出现FileNotFoundError [Errno 2] No such file or directory,这个bug是路径过长,解决方案为吧log日志放在当前目录,或者修改动态生成的文件的名字,给了第一种方式,测试日志放在当前目录) | |||
## qq交流群:194704520 | |||
### 使用的库 requests,绝大部分是基于Python原有的库进行的,这样简单方便, | |||
### 使用脚本参数分离等思想,尽可能降低代码的耦合度。 | |||
### 如果你不配置钉钉机器人,注释到机器人相关的代码 | |||
# 首先我们来看下我们的目录 | |||
## | |||
![Alt text](https://github.com/liwanlei/jiekou-python3/blob/master/img/xiangmujiegoutu.png) | |||
## | |||
### 1.Case文件夹用来存放我们的测试用例相关的, | |||
### 2.test_case用来存储我们的测试数据,Excel管理测试用例,yaml文件管理测试用例,后续要把yaml管理测试用例的也封装出来。 | |||
### 3.Interface对测试接口相关的封装,包括requests库,发送测试报告的email的封装,从Excel取测试数据的封装 | |||
### 4.Public 展示测试报告相关的脚本,这里可以自己封装,也可以使用现成的,我这里是基于我自己封装的,最后生成的测试报告更加易懂,出错可以尽快排查相关原因 | |||
### 5.report 存放测试报告, | |||
### 6.run_excel_re.py/run_html.py 主运行文件。运行后可以生成相应的测试报告 | |||
### 7.run_new新版执行方式,重写了unittest方法,利用ddt驱动,生成漂亮的测试报告 | |||
## | |||
## 除了在github的开源项目的分享,我也运营了自己的公众号,欢迎大家关注我的公众号 | |||
![Alt text](https://github.com/liwanlei/jiekou-python3/blob/master/img/%E5%85%AC%E4%BC%97%E5%8F%B7%E6%B5%B7%E6%8A%A5.jpeg) | |||
## 产生的html测试报告如下 | |||
![Alt text](https://github.com/liwanlei/jiekou/blob/master/img/cebaogaotu.png) | |||
## | |||
### 增加了Excel管理测试报告的功能,目前在继续优化功能,增加了config目录,一些配置文件的目录, | |||
## | |||
## 产生的Excel测试报告如下 | |||
![Alt text](https://github.com/liwanlei/jiekou/blob/master/img/excel.png) | |||
![Alt text](https://github.com/liwanlei/jiekou/blob/master/img/excel2.png) | |||
### 现在的测试结构更加完整,最新的一次提交增加了log日志的展示,使功能更加完善,log日志在控制台展示如下,对目录进行优化 | |||
![Alt text](https://github.com/liwanlei/jiekou/blob/master/img/log.png) | |||
@@ -0,0 +1,5 @@ | |||
""" | |||
@author: lileilei | |||
@file: __init__.py | |||
@time: 2018/4/12 14:17 | |||
""" |
@@ -0,0 +1,8 @@ | |||
""" | |||
@author: lileilei | |||
@file: config.py | |||
@time: 2018/4/12 14:17 | |||
""" | |||
Dingtalk_access_token = "" # 钉钉配置 | |||
TestPlanUrl = 'http://localhost:8881' # 基础url | |||
Config_Try_Num = 1 # 失败重试 |
@@ -0,0 +1,4 @@ | |||
#foremail: '952943386@qq.com' | |||
#password: "zzaikjtenujtbaif" | |||
#toeamil: "leileili126@163.com,952943386@qq.com" | |||
title: "测试报告" |
@@ -0,0 +1,7 @@ | |||
projectname: '图灵' | |||
interfaceVersion: '1.0.1' | |||
tijiao_time: 2023-1-28 | |||
tijiao_person: testTJ | |||
ceshi_person: test1,test2 | |||
ceshi_time: 2023-2-28 | |||
shenhename: shenhe1 |
@@ -0,0 +1 @@ | |||
2_0_0 |
@@ -0,0 +1 @@ | |||
0_2_0 |
@@ -0,0 +1 @@ | |||
0_2_0 |
@@ -0,0 +1 @@ | |||
0_2_0 |
@@ -0,0 +1 @@ | |||
0_2_0 |
@@ -0,0 +1 @@ | |||
0_2_0 |
@@ -0,0 +1 @@ | |||
0_2_0 |
@@ -0,0 +1 @@ | |||
2_0_0 |
@@ -0,0 +1 @@ | |||
2_0_0 |
@@ -0,0 +1 @@ | |||
2_0_0 |
@@ -0,0 +1 @@ | |||
2_0_0 |
@@ -0,0 +1 @@ | |||
2_0_0 |
@@ -0,0 +1 @@ | |||
2_0_0 |
@@ -0,0 +1 @@ | |||
2_0_0 |
@@ -0,0 +1 @@ | |||
2_0_0 |
@@ -0,0 +1 @@ | |||
2_0_0 |
@@ -0,0 +1 @@ | |||
2_0_0 |
@@ -0,0 +1 @@ | |||
2_0_0 |
@@ -0,0 +1 @@ | |||
2_0_0 |
@@ -0,0 +1 @@ | |||
2_0_0 |
@@ -0,0 +1 @@ | |||
2_0_0 |
@@ -0,0 +1 @@ | |||
2_0_0 |
@@ -0,0 +1 @@ | |||
2_0_0 |
@@ -0,0 +1 @@ | |||
2_0_0 |
@@ -0,0 +1 @@ | |||
2_0_0 |
@@ -0,0 +1,48 @@ | |||
[2023-02-19 18:10:29.859856] INFO: interface_case_run: 当前模块 生成数据驱动所用数据 | |||
[2023-02-19 18:10:29.860589] INFO: interface_case_run: 全部args参数参数信息 , () | |||
[2023-02-19 18:10:29.860726] INFO: interface_case_run: 全部kwargs参数信息 , {} | |||
[2023-02-19 18:10:29.860902] INFO: interface_case_run: 当前模块 解析测试用例文件 | |||
[2023-02-19 18:10:29.861022] INFO: interface_case_run: 全部args参数参数信息 , ('/Users/lileilei/Desktop/testplan/jiekou-python3/test_case_data/case.xlsx',) | |||
[2023-02-19 18:10:29.861131] INFO: interface_case_run: 全部kwargs参数信息 , {} | |||
[2023-02-19 18:10:29.890171] INFO: interface_case_run: 测试用例开始执行 | |||
[2023-02-19 18:10:29.890499] INFO: interface_case_run: {'key': 'aaaa', 'info': {'password': '1222'}} | |||
[2023-02-19 18:10:29.890675] INFO: interface_case_run: 输入参数:url:/openapi/api,key:aaaa,参数:{'password':'1222'},请求方式:POST | |||
[2023-02-19 18:10:29.890808] INFO: interface_case_run: 输入参数:url:/openapi/api,key:aaaa,参数:{'password':'1222'},请求方式:None | |||
[2023-02-19 18:10:29.963764] INFO: interface_case_run: 返回结果:{'code': 0, 'result': {'code': 40007, 'text': '您的请求内容为空。'}} | |||
[2023-02-19 18:10:29.964209] INFO: interface_case_run: 当前模块 断言测试结果 | |||
[2023-02-19 18:10:29.964440] INFO: interface_case_run: 全部args参数参数信息 , () | |||
[2023-02-19 18:10:29.964621] INFO: interface_case_run: 全部kwargs参数信息 , {'asserassert': 'code=40001'} | |||
[2023-02-19 18:10:29.964853] INFO: interface_case_run: 测试用例执行完毕 | |||
[2023-02-19 18:10:29.965177] INFO: interface_case_run: 测试用例开始执行 | |||
[2023-02-19 18:10:29.965522] INFO: interface_case_run: {'key': 'dfeb1cc8125943d29764a2f2f5c33739', 'info': {'password': '1222'}} | |||
[2023-02-19 18:10:29.965771] INFO: interface_case_run: 输入参数:url:/openapi/api,key:dfeb1cc8125943d29764a2f2f5c33739,参数:{'password':'1222'},请求方式:POST | |||
[2023-02-19 18:10:29.965956] INFO: interface_case_run: 输入参数:url:/openapi/api,key:dfeb1cc8125943d29764a2f2f5c33739,参数:{'password':'1222'},请求方式:None | |||
[2023-02-19 18:10:30.008491] INFO: interface_case_run: 返回结果:{'code': 0, 'result': {'code': 40007, 'text': '您的请求内容为空。'}} | |||
[2023-02-19 18:10:30.008802] INFO: interface_case_run: 当前模块 断言测试结果 | |||
[2023-02-19 18:10:30.009003] INFO: interface_case_run: 全部args参数参数信息 , () | |||
[2023-02-19 18:10:30.009179] INFO: interface_case_run: 全部kwargs参数信息 , {'asserassert': 'code=40002'} | |||
[2023-02-19 18:10:30.009398] INFO: interface_case_run: 测试用例执行完毕 | |||
[2023-02-19 18:10:47.409761] INFO: interface_case_run: 当前模块 生成数据驱动所用数据 | |||
[2023-02-19 18:10:47.410094] INFO: interface_case_run: 全部args参数参数信息 , () | |||
[2023-02-19 18:10:47.410218] INFO: interface_case_run: 全部kwargs参数信息 , {} | |||
[2023-02-19 18:10:47.410376] INFO: interface_case_run: 当前模块 解析测试用例文件 | |||
[2023-02-19 18:10:47.410492] INFO: interface_case_run: 全部args参数参数信息 , ('/Users/lileilei/Desktop/testplan/jiekou-python3/test_case_data/case.xlsx',) | |||
[2023-02-19 18:10:47.410600] INFO: interface_case_run: 全部kwargs参数信息 , {} | |||
[2023-02-19 18:10:47.430403] INFO: interface_case_run: 测试用例开始执行 | |||
[2023-02-19 18:10:47.430650] INFO: interface_case_run: {'key': 'aaaa', 'info': {'password': '1222'}} | |||
[2023-02-19 18:10:47.430796] INFO: interface_case_run: 输入参数:url:/openapi/api,key:aaaa,参数:{'password':'1222'},请求方式:POST | |||
[2023-02-19 18:10:47.430936] INFO: interface_case_run: 输入参数:url:/openapi/api,key:aaaa,参数:{'password':'1222'},请求方式:None | |||
[2023-02-19 18:10:47.481670] INFO: interface_case_run: 返回结果:{'code': 0, 'result': {'code': 40007, 'text': '您的请求内容为空。'}} | |||
[2023-02-19 18:10:47.482034] INFO: interface_case_run: 当前模块 断言测试结果 | |||
[2023-02-19 18:10:47.482468] INFO: interface_case_run: 全部args参数参数信息 , () | |||
[2023-02-19 18:10:47.482886] INFO: interface_case_run: 全部kwargs参数信息 , {'asserassert': 'code=40001'} | |||
[2023-02-19 18:10:47.483244] INFO: interface_case_run: 测试用例执行完毕 | |||
[2023-02-19 18:10:47.483554] INFO: interface_case_run: 测试用例开始执行 | |||
[2023-02-19 18:10:47.483789] INFO: interface_case_run: {'key': 'dfeb1cc8125943d29764a2f2f5c33739', 'info': {'password': '1222'}} | |||
[2023-02-19 18:10:47.483958] INFO: interface_case_run: 输入参数:url:/openapi/api,key:dfeb1cc8125943d29764a2f2f5c33739,参数:{'password':'1222'},请求方式:POST | |||
[2023-02-19 18:10:47.484095] INFO: interface_case_run: 输入参数:url:/openapi/api,key:dfeb1cc8125943d29764a2f2f5c33739,参数:{'password':'1222'},请求方式:None | |||
[2023-02-19 18:10:47.527872] INFO: interface_case_run: 返回结果:{'code': 0, 'result': {'code': 40007, 'text': '您的请求内容为空。'}} | |||
[2023-02-19 18:10:47.528236] INFO: interface_case_run: 当前模块 断言测试结果 | |||
[2023-02-19 18:10:47.528482] INFO: interface_case_run: 全部args参数参数信息 , () | |||
[2023-02-19 18:10:47.528716] INFO: interface_case_run: 全部kwargs参数信息 , {'asserassert': 'code=40002'} | |||
[2023-02-19 18:10:47.528998] INFO: interface_case_run: 测试用例执行完毕 |
@@ -0,0 +1,44 @@ | |||
[2023-02-28 15:45:50.574267] INFO: interface_case_run: 当前模块 解析测试用例文件 | |||
[2023-02-28 15:45:50.577260] INFO: interface_case_run: 全部args参数参数信息 , ('E:\\zq\\project\\liwanlei\\jiekou-python3\\test_case_data\\case.xlsx',) | |||
[2023-02-28 15:45:50.578256] INFO: interface_case_run: 全部kwargs参数信息 , {} | |||
[2023-02-28 15:45:50.617180] INFO: interface_case_run: 当前模块 解析测试用例文件 | |||
[2023-02-28 15:45:50.619180] INFO: interface_case_run: 全部args参数参数信息 , ('E:\\zq\\project\\liwanlei\\jiekou-python3\\test_case_data\\case.xlsx',) | |||
[2023-02-28 15:45:50.623139] INFO: interface_case_run: 全部kwargs参数信息 , {} | |||
[2023-02-28 15:45:50.631140] INFO: interface_case_run: 当前模块 测试 | |||
[2023-02-28 15:45:50.633135] INFO: interface_case_run: 全部args参数参数信息 , () | |||
[2023-02-28 15:45:50.635128] INFO: interface_case_run: 全部kwargs参数信息 , {} | |||
[2023-02-28 15:45:50.658045] INFO: interface_case_run: inputdata> 参数:{"password":"1222"}, url:/ ,返回:{'code': 0, 'result': {'code': '400', 'msg': 'success', 'data': '123123'}},预期:code=400 | |||
[2023-02-28 15:45:50.660072] INFO: interface_case_run: 当前模块 断言测试结果 | |||
[2023-02-28 15:45:50.662033] INFO: interface_case_run: 全部args参数参数信息 , () | |||
[2023-02-28 15:45:50.664060] INFO: interface_case_run: 全部kwargs参数信息 , {'asserassert': 'code=400', 'returnjson': {'code': 0, 'result': {'code': '400', 'msg': 'success', 'data': '123123'}}} | |||
[2023-02-28 15:45:50.666055] INFO: interface_case_run: 失败重试中 | |||
[2023-02-28 15:45:50.676990] INFO: interface_case_run: inputdata> 参数:{"password":"1222"}, url:/ ,返回:{'code': 0, 'result': {'code': '400', 'msg': 'success', 'data': '123123'}},预期:code=400 | |||
[2023-02-28 15:45:50.679987] INFO: interface_case_run: 当前模块 断言测试结果 | |||
[2023-02-28 15:45:50.681981] INFO: interface_case_run: 全部args参数参数信息 , () | |||
[2023-02-28 15:45:50.683976] INFO: interface_case_run: 全部kwargs参数信息 , {'asserassert': 'code=400', 'returnjson': {'code': 0, 'result': {'code': '400', 'msg': 'success', 'data': '123123'}}} | |||
[2023-02-28 15:45:50.685968] INFO: interface_case_run: 失败重试中 | |||
[2023-02-28 15:45:50.694946] INFO: interface_case_run: inputdata> 参数:{"password":"1222"}, url:/ ,返回:{'code': 0, 'result': {'code': '400', 'msg': 'success', 'data': '123123'}},预期:code=400 | |||
[2023-02-28 15:45:50.696968] INFO: interface_case_run: 当前模块 断言测试结果 | |||
[2023-02-28 15:45:50.698963] INFO: interface_case_run: 全部args参数参数信息 , () | |||
[2023-02-28 15:45:50.700926] INFO: interface_case_run: 全部kwargs参数信息 , {'asserassert': 'code=400', 'returnjson': {'code': 0, 'result': {'code': '400', 'msg': 'success', 'data': '123123'}}} | |||
[2023-02-28 15:45:50.702924] INFO: interface_case_run: 失败重试中次数用完,最后结果 | |||
[2023-02-28 15:45:50.713897] INFO: interface_case_run: inputdata> 参数:{"password":"1222"}, url:/ ,返回:{'code': 0, 'result': {'code': '400', 'msg': 'success', 'data': '123123'}},预期:code=400 | |||
[2023-02-28 15:45:50.716886] INFO: interface_case_run: 当前模块 断言测试结果 | |||
[2023-02-28 15:45:50.718882] INFO: interface_case_run: 全部args参数参数信息 , () | |||
[2023-02-28 15:45:50.721871] INFO: interface_case_run: 全部kwargs参数信息 , {'asserassert': 'code=400', 'returnjson': {'code': 0, 'result': {'code': '400', 'msg': 'success', 'data': '123123'}}} | |||
[2023-02-28 15:45:50.723900] INFO: interface_case_run: 失败重试中 | |||
[2023-02-28 15:45:50.731844] INFO: interface_case_run: inputdata> 参数:{"password":"1222"}, url:/ ,返回:{'code': 0, 'result': {'code': '400', 'msg': 'success', 'data': '123123'}},预期:code=400 | |||
[2023-02-28 15:45:50.733862] INFO: interface_case_run: 当前模块 断言测试结果 | |||
[2023-02-28 15:45:50.735865] INFO: interface_case_run: 全部args参数参数信息 , () | |||
[2023-02-28 15:45:50.737826] INFO: interface_case_run: 全部kwargs参数信息 , {'asserassert': 'code=400', 'returnjson': {'code': 0, 'result': {'code': '400', 'msg': 'success', 'data': '123123'}}} | |||
[2023-02-28 15:45:50.739853] INFO: interface_case_run: 失败重试中 | |||
[2023-02-28 15:45:50.748798] INFO: interface_case_run: inputdata> 参数:{"password":"1222"}, url:/ ,返回:{'code': 0, 'result': {'code': '400', 'msg': 'success', 'data': '123123'}},预期:code=400 | |||
[2023-02-28 15:45:50.750793] INFO: interface_case_run: 当前模块 断言测试结果 | |||
[2023-02-28 15:45:50.752813] INFO: interface_case_run: 全部args参数参数信息 , () | |||
[2023-02-28 15:45:50.754784] INFO: interface_case_run: 全部kwargs参数信息 , {'asserassert': 'code=400', 'returnjson': {'code': 0, 'result': {'code': '400', 'msg': 'success', 'data': '123123'}}} | |||
[2023-02-28 15:45:50.756776] INFO: interface_case_run: 失败重试中次数用完,最后结果 | |||
[2023-02-28 15:45:50.767752] INFO: interface_case_run: 失败重试中 | |||
[2023-02-28 15:45:50.784705] INFO: interface_case_run: 失败重试中次数用完,最后结果 | |||
[2023-02-28 15:45:50.787698] INFO: interface_case_run: 当前模块 保存测试结果 | |||
[2023-02-28 15:45:50.789692] INFO: interface_case_run: 全部args参数参数信息 , (datetime.datetime(2023, 2, 28, 15, 45, 50, 617180), 3, 0, 2) | |||
[2023-02-28 15:45:50.791719] INFO: interface_case_run: 全部kwargs参数信息 , {} |
@@ -0,0 +1,27 @@ | |||
记录测试时间,测试总数,pass数量,失败数量 用‘=’拼接 | |||
2017-10-16 20:54:56.323951=3=3=0 | |||
2020-11-22 11:19:17.653613=2=0=2 | |||
2020-11-22 11:19:55.276935=2=0=2 | |||
2020-11-22 11:20:03.408231=2=0=2 | |||
2020-11-22 11:20:22.107504=2=0=2 | |||
2022-01-15 13:37:10.453363=2=0=2 | |||
2022-01-15 13:37:53.945016=2=0=2 | |||
2022-01-15 13:38:07.907832=2=0=2 | |||
2022-01-15 13:38:16.052044=2=0=2 | |||
2022-01-15 13:39:41.019636=2=0=2 | |||
2022-01-15 13:39:51.378087=2=0=2 | |||
2022-01-15 13:40:33.036679=2=0=2 | |||
2022-04-22 17:22:26.808171=2=0=2 | |||
2023-02-19 18:06:12.486185=2=0=2 | |||
2023-02-19 18:06:17.821946=2=0=2 | |||
2023-02-28 15:12:05.803270=3=0=0 | |||
2023-02-28 15:16:10.287783=3=0=0 | |||
2023-02-28 15:16:49.591922=3=0=0 | |||
2023-02-28 15:17:30.399087=3=0=0 | |||
2023-02-28 15:19:47.649372=3=0=0 | |||
2023-02-28 15:22:16.319412=3=0=0 | |||
2023-02-28 15:24:43.906041=3=0=0 | |||
2023-02-28 15:33:12.201676=3=0=2 | |||
2023-02-28 15:34:42.006208=3=0=1 | |||
2023-02-28 15:43:50.790958=3=0=2 | |||
2023-02-28 15:45:50.617180=3=0=2 |
@@ -0,0 +1,38 @@ | |||
# encoding: utf-8 | |||
""" | |||
@author: lileilei | |||
@file: run_excel_re.py | |||
@time: 2017/6/9 12:45 | |||
""" | |||
from Public.pyreport_excel import create | |||
import os, threading, datetime | |||
from testCase.case import testinterface | |||
from Public.get_excel import datacel | |||
from Public.create_report import save_result | |||
def start(): | |||
starttime = datetime.datetime.now() | |||
mtime = datetime.datetime.now().strftime("%Y%m%d") | |||
basdir = os.path.abspath(os.path.dirname(__file__)) | |||
path = os.path.join(os.path.join(os.getcwd(), 'test_case_data'), 'case.xlsx') | |||
listid, listkey, listconeent, listurl, listmethod, listqiwang, listname = datacel(path) | |||
listrelust, list_fail, list_pass, list_json, list_weizhi, listone = testinterface() | |||
filepath = os.path.join(os.path.join(basdir, 'test_Report'), '%s-result.xls' % mtime) | |||
if os.path.exists(filepath) is False: | |||
os.system(r'touch %s' % filepath) | |||
save_result(starttime, len(listrelust), ((list_pass)), list_fail) | |||
create(filename=filepath, list_fail=list_fail, list_pass=list_pass, list_json=list_json, listurls=listurl, | |||
listkeys=listkey, listconeents=listconeent, listfangshis=listmethod, | |||
listqiwangs=listqiwang, | |||
listids=listid, listrelust=listrelust, listnames=listname) | |||
def teThread(): | |||
m = threading.Thread(target=start, args=()) | |||
m.run() | |||
if __name__ == '__main__': | |||
teThread() |
@@ -0,0 +1,36 @@ | |||
# -*- coding: utf-8 -*- | |||
# @Author : leizi | |||
import os, datetime, time | |||
from testCase.case import testinterface | |||
from Public.py_Html import createHtml | |||
from Public.get_excel import datacel | |||
from Public.create_report import save_result | |||
import threading | |||
def stast(): | |||
starttime = datetime.datetime.now() | |||
day = time.strftime("%Y%m%d%H%M", time.localtime(time.time())) | |||
path = os.path.join(os.path.join(os.getcwd(), 'test_case_data'), 'case.xlsx') | |||
basdir = os.path.abspath(os.path.dirname(__file__)) | |||
listid, listkey, listconeent, listurl, listfangshi, listqiwang, listname = datacel(path) | |||
listrelust, list_fail, list_pass, list_json, list_exption, list_weizhi = testinterface() | |||
filepath = os.path.join(os.path.join(basdir, 'test_Report'), '%s-result.html' % day) | |||
if os.path.exists(filepath) is False: | |||
os.system(r'touch %s' % filepath) | |||
save_result(starttime, len(listrelust), ((list_pass)), list_fail) | |||
endtime = datetime.datetime.now() | |||
createHtml(titles='接口测试报告', filepath=filepath, starttime=starttime, | |||
endtime=endtime, passge=list_pass, fail=list_fail, | |||
id=listid, name=listname, key=listkey, coneent=listconeent, url=listurl, meth=listfangshi, | |||
yuqi=listqiwang, json=list_json, relusts=listrelust, exceptions=list_exption, weizhi=list_weizhi) | |||
# sendemali(filepath) | |||
def tThread(): | |||
m = threading.Thread(target=stast, args=()) | |||
m.run() | |||
if __name__ == '__main__': | |||
tThread() |
@@ -0,0 +1,38 @@ | |||
# -*- coding: utf-8 -*- | |||
# @Author : leizi | |||
import os, datetime, time | |||
from testCase.case import testinterface | |||
from public.py_Html import createHtml | |||
from public.get_excel import datacel | |||
from public.Dingtalk import send_ding | |||
'''执行测试的主要文件''' | |||
def start_interface_html_http(): | |||
starttime = datetime.datetime.now() | |||
day = time.strftime("%Y%m%d%H%M", time.localtime(time.time())) | |||
basdir = os.path.abspath(os.path.dirname(__file__)) | |||
path = os.path.join(os.path.join(os.getcwd(), 'test_case_data'), 'case.xlsx') | |||
listid, listkey, listconeent, listurl, listfangshi, listqiwang, listname = datacel(path) | |||
listrelust, list_fail, list_pass, list_json, list_exption, list_weizhi = testinterface() | |||
filepath = os.path.join(os.path.join(basdir, 'test_Report'), '%s-result.html' % day) | |||
if os.path.exists(filepath) is False: | |||
os.system(r'touch %s' % filepath) | |||
endtime = datetime.datetime.now() | |||
createHtml(titles=u'http接口自动化测试报告', filepath=filepath, starttime=starttime, | |||
endtime=endtime, passge=list_pass, fail=list_fail, | |||
id=listid, name=listname, key=listkey, coneent=listconeent, url=listurl, meth=listfangshi, | |||
yuqi=listqiwang, json=list_json, relusts=listrelust, weizhi=list_weizhi, exceptions=list_exption) | |||
# contec = u'http接口自动化测试完成,测试通过:%s,测试失败:%s,异常:%s,未知错误:%s,详情见:%s' % ( | |||
# list_pass, list_fail, list_exption, list_weizhi, filepath) | |||
# send_ding(content=contec) | |||
if __name__ == '__main__': | |||
start_interface_html_http() |
@@ -0,0 +1,27 @@ | |||
# -*- coding: utf-8 -*- | |||
# @Author : leizi | |||
from testCase.ddt_case import MyTest | |||
import unittest, time, os | |||
from public import BSTestRunner | |||
BASH_DIR = "history" | |||
if __name__ == '__main__': | |||
basedir = os.path.abspath(os.path.dirname(__file__)) | |||
file_dir = os.path.join(basedir, 'test_Report') | |||
file_reslut = os.path.join(file_dir, 'caseresult.yaml') | |||
try: | |||
os.remove(file_reslut) | |||
except: | |||
pass | |||
suite = unittest.TestSuite() | |||
suite.addTests(unittest.TestLoader().loadTestsFromTestCase(MyTest)) | |||
now = time.strftime('%Y-%m%d', time.localtime(time.time())) | |||
file = os.path.join(file_dir, (now + '.html')) | |||
re_open = open(file, 'wb') | |||
besautiful = BSTestRunner.BSTestRunner(title="报告", | |||
description="测试报告", | |||
stream=re_open, | |||
trynum=3, | |||
filepath=BASH_DIR, | |||
is_show=True) | |||
besautiful.run(suite) |
@@ -0,0 +1,86 @@ | |||
# -*- coding: utf-8 -*- | |||
# @Time : 2017/6/4 20:15 | |||
# @Author : lileilei | |||
# @File : case.py | |||
from Interface.testFengzhuang import TestApi | |||
from Public.get_excel import datacel | |||
from Public.log import LOG, logger | |||
import os | |||
from config.config import Config_Try_Num, TestPlanUrl | |||
path = os.path.join(os.path.join(os.getcwd(), 'test_case_data'), 'case.xlsx') | |||
listid, listkey, listconeent, listurl, listfangshi, listqiwang, listname = datacel(path) | |||
from Public.panduan import assert_in | |||
@logger('测试') | |||
def testinterface(): | |||
list_pass = 0 | |||
list_fail = 0 | |||
list_json = [] | |||
listrelust = [] | |||
list_weizhi = 0 | |||
list_exption = 0 | |||
error_num = 0 | |||
for i in range(len(listurl)): | |||
while error_num <= Config_Try_Num + 1: | |||
parem = {'key': listkey[i]} | |||
parem.update({'info': eval(listconeent[i])}) | |||
#parem=eval(data_test[listconeent[i]) | |||
api = TestApi(url=TestPlanUrl + listurl[i], parame=parem, method=listfangshi[i]) | |||
apijson = api.getJson() | |||
if apijson['code'] == 0: | |||
LOG.info('inputdata> 参数:%s, url:%s ,返回:%s,预期:%s' % (listconeent[i], listurl[i], apijson, listqiwang[i])) | |||
assert_re = assert_in(asserassert=listqiwang[i], returnjson=apijson) | |||
if assert_re['code'] == 0: | |||
list_json.append(apijson['result']) | |||
listrelust.append('pass') | |||
list_pass += 1 | |||
error_num = 0 | |||
continue | |||
elif assert_re['code'] == 1: | |||
if error_num <= Config_Try_Num: | |||
error_num += 1 | |||
LOG.info('失败重试中') | |||
else: | |||
LOG.info('失败重试中次数用完,最后结果') | |||
error_num = 0 | |||
list_fail += 1 | |||
listrelust.append('fail') | |||
list_json.append(apijson['result']) | |||
break | |||
elif assert_re['code'] == 2: | |||
if error_num < Config_Try_Num: | |||
error_num += 1 | |||
LOG.info('失败重试中') | |||
else: | |||
LOG.info('失败重试中次数用完,最后结果') | |||
error_num = 0 | |||
list_exption += 1 | |||
listrelust.append('exception') | |||
list_json.append(assert_re['result']) | |||
break | |||
else: | |||
if error_num < Config_Try_Num: | |||
error_num += 1 | |||
LOG.info('失败重试中') | |||
else: | |||
LOG.info('失败重试中次数用完,最后结果') | |||
error_num = 0 | |||
list_weizhi += 1 | |||
listrelust.append('未知错误') | |||
list_json.append('未知错误') | |||
break | |||
else: | |||
if error_num < Config_Try_Num: | |||
error_num += 1 | |||
LOG.info('失败重试中') | |||
else: | |||
LOG.info('失败重试中次数用完,最后结果') | |||
error_num = 0 | |||
list_exption += 1 | |||
listrelust.append('exception') | |||
list_json.append(apijson['result']) | |||
break | |||
return listrelust, list_fail, list_pass, list_json, list_exption, list_weizhi |
@@ -0,0 +1,79 @@ | |||
import ddt, unittest, os, yaml | |||
from Interface.testFengzhuang import TestApi | |||
from public.get_excel import makedata | |||
from public.log import LOG | |||
from public.panduan import assertre | |||
from config.config import TestPlanUrl | |||
file_dir = os.path.join(os.getcwd(), 'test_Report') | |||
file_reslut = os.path.join(file_dir, 'caseresult.yaml') | |||
data_test = makedata() | |||
def write(data): | |||
with open(file_reslut, 'a', encoding='utf-8') as f: | |||
yaml.dump(data, f, allow_unicode=True) | |||
def read(data): | |||
f = open(file_reslut, 'r', encoding='utf-8') | |||
d = yaml.load(f, Loader=yaml.FullLoader) | |||
return d[data] | |||
@ddt.ddt | |||
class MyTest(unittest.TestCase): | |||
def setUp(self): | |||
LOG.info('测试用例开始执行') | |||
def tearDown(self): | |||
LOG.info('测试用例执行完毕') | |||
@ddt.data(*data_test) | |||
def test_api(self, data_test): | |||
''' | |||
1.处理参数 | |||
2.判断参数是否有依赖 | |||
3.依赖用例参数从本地获取 | |||
4.获取失败,用例失败 | |||
5.拼接后请求 | |||
''' | |||
parem = {'key': data_test['key']} | |||
try: | |||
parem_dict = eval(data_test['coneent']) | |||
for key, value in parem_dict.items(): | |||
if str(value).startswith("&"): | |||
try: | |||
reply_key_id = str(value).split("&")[-1].split("=") | |||
reply_keyid = reply_key_id[0] | |||
reply_key_key = reply_key_id[1] | |||
reslut = read(reply_keyid) | |||
if reslut is None: | |||
self.assertTrue(False, '依赖用例获取失败') | |||
get_value = reslut[reply_key_key] | |||
if get_value is None: | |||
self.assertTrue(False, '依赖参数获取失败,不存在') | |||
parem_dict[key] = get_value | |||
except Exception as e: | |||
LOG.info("用例依赖执行失败:" + str(e)) | |||
self.assertTrue(False, '用例依赖执行失败') | |||
parem.update({'info': parem_dict}) | |||
except: | |||
self.assertTrue(False, msg="参数格式不对") | |||
LOG.info(parem) | |||
api = TestApi(url=TestPlanUrl + data_test['url'], | |||
parame=parem, | |||
method=data_test['method']) | |||
LOG.info('输入参数:url:%s,key:%s,参数:%s,请求方式:%s' % (data_test['url'], data_test['key'], data_test['assertconnect'], | |||
LOG.info('输入参数:url:%s,key:%s,参数:%s,请求方式:%s' % ( | |||
data_test['url'], data_test['key'], data_test['assertconnect'], | |||
data_test['method'])))) | |||
apijson = api.getJson() | |||
reslut = {} | |||
reslut[data_test['id']] = apijson | |||
write(reslut) | |||
LOG.info('返回结果:%s' % apijson) | |||
assertall = assertre(asserassert=data_test['assertconnect']) | |||
self.assertNotEqual(dict(assertall), dict(apijson), msg='预期和返回不一致') |
@@ -0,0 +1,52 @@ | |||
""" | |||
@author: lileilei | |||
@file: dubbocase.py | |||
@time: 2018/3/29 12:47 | |||
""" | |||
from Interface.dubbo_feng import DubboInterface | |||
from public.log import LOG, logger | |||
from public.panduan import assert_in | |||
from public.get_excel import datacel | |||
import os | |||
path = os.path.join(os.path.join(os.getcwd(), 'test_case_data'), 'dubbocase.xlsx') | |||
listid, listurl, listinterface, listmeth, listfobject, listparam, listassert = datacel(path) | |||
@logger('dubbo接口测试') | |||
def testdubbointerface(): | |||
list_pass = 0 | |||
list_fail = 0 | |||
list_json = [] | |||
listrelust = [] | |||
list_weizhi = 0 | |||
list_exption = 0 | |||
for i in range(len(listid)): | |||
dubboapi = DubboInterface(url=listurl, interface=listinterface[i], method=listmeth[i], param=listfobject[i], | |||
**(eval(listparam[i]))) | |||
dubboapireslu = dubboapi.getresult() | |||
if dubboapireslu['code'] == 0: | |||
LOG.info('inputdata> 参数:%s, url:%s ,返回:%s,预期:%s' % (listparam[i], listurl[i], dubboapireslu, listassert[i])) | |||
assert_re = assert_in(asserassert=listassert[i], returnjson=dubboapireslu) | |||
if assert_re['code'] == 0: | |||
list_json.append(dubboapireslu['result']) | |||
listrelust.append('pass') | |||
list_pass += 1 | |||
elif assert_re['code'] == 1: | |||
list_fail += 1 | |||
listrelust.append('fail') | |||
list_json.append(dubboapireslu['result']) | |||
elif assert_re['code'] == 2: | |||
list_exption += 1 | |||
listrelust.append('exception') | |||
list_json.append(assert_re['result']) | |||
else: | |||
list_weizhi += 1 | |||
listrelust.append('未知错误') | |||
list_json.append('未知错误') | |||
else: | |||
list_exption += 1 | |||
listrelust.append('exception') | |||
list_json.append(dubboapireslu['result']) | |||
continue | |||
return listrelust, list_fail, list_pass, list_json, list_exption, list_weizhi |
@@ -0,0 +1,64 @@ | |||
''' | |||
@Description | |||
@auther leizi | |||
''' | |||
from Interface.testFengzhuang import TestApi | |||
from public.log import LOG | |||
from public.panduan import assertre | |||
from config.config import TestPlanUrl | |||
import pytest | |||
import os | |||
import yaml | |||
from public.get_excel import makedata | |||
file_dir = os.path.join(os.getcwd(), 'test_Report') | |||
file_reslut = os.path.join(file_dir, 'caseresult.yaml') | |||
def write(data): | |||
with open(file_reslut, 'a', encoding='utf-8') as f: | |||
yaml.dump(data, f, allow_unicode=True) | |||
def read(data): | |||
f = open(file_reslut, 'r', encoding='utf-8') | |||
d = yaml.load(f, Loader=yaml.FullLoader) | |||
return d[data] | |||
data_test = makedata() | |||
@pytest.mark.parametrize(data_test) | |||
class TestParametrize(object): | |||
def test_parame(self): | |||
parem = {'key': data_test['key']} | |||
try: | |||
parem_dict = eval(data_test['coneent']) | |||
for key, value in parem_dict.items(): | |||
if str(value).startswith("&"): | |||
try: | |||
reply_key_id = str(value).split("&")[-1].split("=") | |||
reply_keyid = reply_key_id[0] | |||
reply_key_key = reply_key_id[1] | |||
reslut = read(reply_keyid) | |||
if reslut is None: | |||
assert False | |||
get_value = reslut[reply_key_key] | |||
if get_value is None: | |||
assert False | |||
parem_dict[key] = get_value | |||
except Exception as e: | |||
LOG.info("用例依赖执行失败:" + str(e)) | |||
assert False | |||
parem.update({'info': parem_dict}) | |||
except: | |||
assert False | |||
api = TestApi(url=TestPlanUrl + data_test['url'], | |||
parame=parem, | |||
method=data_test['fangshi']) | |||
LOG.info('输入参数:url:%s,key:%s,参数:%s,请求方式:%s' % (data_test['url'], data_test['key'], data_test['coneent'], | |||
LOG.info('输入参数:url:%s,key:%s,参数:%s,请求方式:%s' % ( | |||
data_test['url'], data_test['key'], data_test['coneent'], | |||
data_test['fangshi'])))) | |||
apijson = api.getJson() | |||
reslut = {} | |||
reslut[data_test['id']] = apijson | |||
LOG.info('返回结果:%s' % apijson) | |||
assertall = assertre(asserassert=data_test['qiwang']) | |||
assert dict(assertall) == dict(apijson) |
@@ -0,0 +1,264 @@ | |||
<!DOCTYPE html> | |||
<html lang="zh-cn"> | |||
<head> | |||
<meta charset="utf-8"> | |||
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |||
<meta name="viewport" content="width=device-width, initial-scale=1"> | |||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | |||
<title>报告</title> | |||
<meta name="generator" content="BSTestRunner 0.8.4"/> | |||
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" "> | |||
<script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script> | |||
<style type="text/css" media="screen"> | |||
/* -- css div popup ------------------------------------------------------------------------ */ | |||
.popup_window { | |||
display: none; | |||
position: relative; | |||
left: 0px; | |||
top: 0px; | |||
/*border: solid #627173 1px; */ | |||
padding: 10px; | |||
background-color: #99CCFF; | |||
font-family: "Lucida Console", "Courier New", Courier, monospace; | |||
text-align: left; | |||
font-size: 10pt; | |||
width: 1200px; | |||
} | |||
/* -- report ------------------------------------------------------------------------ */ | |||
#show_detail_line .label { | |||
font-size: 85%; | |||
cursor: pointer; | |||
} | |||
#show_detail_line { | |||
margin: 2em auto 1em auto; | |||
} | |||
#total_row { font-weight: bold; } | |||
.hiddenRow { display: none; } | |||
.testcase { margin-left: 2em; } | |||
</style> | |||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --> | |||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// --> | |||
<!--[if lt IE 9]> | |||
<script src="http://cdn.bootcss.com/html5shiv/3.7.2/html5shiv.min.js"></script> | |||
<script src="http://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script> | |||
<![endif]--> | |||
</head> | |||
<body> | |||
<div class="container"> | |||
<div class='heading'> | |||
<div style='width: 50%;float:left;margin-top:inherit'> | |||
<h1>报告</h1> | |||
<p><strong>开始时间:</strong> 2023-02-19 18:10:47</p> | |||
<p><strong>持续时间:</strong> 0:00:00.099009</p> | |||
<p><strong>状态:</strong> <span class="text text-success">通过 <strong>2</strong></span></p> | |||
<p class='description'>测试报告</p> | |||
</div> | |||
<div id='container2' style='width:50%;float:left;margin-top:20px;height:200px;'> | |||
</div> | |||
</div > | |||
<div id='containerchart' style='height: 300px;margin-top: 20%;'></div> | |||
<p id='show_detail_line'> | |||
<span class="label label-primary" onclick="showCase(0)">公用</span> | |||
<span class="label label-danger" onclick="showCase(1)">失败</span> | |||
<span class="label label-default" onclick="showCase(2)">所有</span> | |||
</p> | |||
<table id='result_table' class="table"> | |||
<thead> | |||
<tr id='header_row'> | |||
<th>测试组/测试用例</td> | |||
<th>数量</td> | |||
<th>通过</td> | |||
<th>失败</td> | |||
<th>错误</td> | |||
<th>查看</td> | |||
</tr> | |||
</thead> | |||
<tbody> | |||
<tr class='text text-success'> | |||
<td>testCase.ddt_case.MyTest</td> | |||
<td>2</td> | |||
<td>2</td> | |||
<td>0</td> | |||
<td>0</td> | |||
<td><a class="btn btn-xs btn-primary"href="javascript:showClassDetail('c1',2)">详情</a></td> | |||
</tr> | |||
<tr id='pt1.1' class='hiddenRow'> | |||
<td class='text text-success'><div class='testcase'>test_api_1: 1.处理参数</div></td> | |||
<td colspan='5' align='center'>通过</td> | |||
</tr> | |||
<tr id='pt1.2' class='hiddenRow'> | |||
<td class='text text-success'><div class='testcase'>test_api_2: 1.处理参数</div></td> | |||
<td colspan='5' align='center'>通过</td> | |||
</tr> | |||
</tbody> | |||
<tfoot> | |||
<tr id='total_row'> | |||
<td>总计</td> | |||
<td>2</td> | |||
<td class="text text-success">2</td> | |||
<td class="text text-danger">0</td> | |||
<td class="text text-warning">0</td> | |||
<td> </td> | |||
</tr> | |||
</tfoot> | |||
</table> | |||
<div id='ending'> </div> | |||
</div> | |||
<script language='javascript' type='text/javascript'> | |||
var dom = document.getElementById('containerchart'); | |||
var myChart = echarts.init(dom); | |||
var domone = document.getElementById('container2'); | |||
var myChartone = echarts.init(domone); | |||
var optionsone; | |||
optionsone = { | |||
title: { | |||
text: '历史记录' | |||
}, | |||
tooltip: { | |||
trigger: 'axis' | |||
}, | |||
legend: { | |||
data: ['成功', '失败','错误'] | |||
}, | |||
grid: { | |||
left: '3%', | |||
right: '4%', | |||
bottom: '3%', | |||
containLabel: true | |||
}, | |||
toolbox: { | |||
feature: { | |||
saveAsImage: {} | |||
} | |||
}, | |||
xAxis: { | |||
type: 'category', | |||
boundaryGap: false, | |||
data: ['2022_04_22_21_06_05', '2022_01_16_09_43_50', '2023_02_19_18_10_30', '2022_04_22_21_22_01', '2022_04_22_21_29_08', '2022_01_16_09_43_56', '2022_01_16_09_41_37', '2022_04_22_17_22_51', '2022_01_16_09_39_12', '2022_01_15_14_26_21', '2023_02_19_18_10_47', '2022_01_16_09_41_00', '2022_01_16_09_39_32', '2022_01_16_09_44_26', '2022_04_22_21_32_40', '2022_01_16_09_46_33', '2022_01_16_09_43_15', '2023_02_19_18_06_29', '2023_02_19_18_08_39', '2022_01_16_09_44_35', '2022_01_16_09_45_12', '2022_01_16_09_39_51', '2022_01_16_09_42_37', '2022_01_16_09_38_16', '2022_01_16_09_36_13'] | |||
}, | |||
yAxis: { | |||
type: 'value' | |||
}, | |||
series: [ | |||
{ | |||
name: '成功', | |||
type: 'line', | |||
stack: '总量', | |||
data: ['2', '2', '2', '2', '2', '2', '2', '2', '0', '2', '2', '0', '0', '2', '2', '2', '2', '2', '2', '2', '2', '0', '2', '0', '0'] | |||
}, | |||
{ | |||
name: '失败', | |||
type: 'line', | |||
stack: '总量', | |||
data: ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'] | |||
}, | |||
{ | |||
name: '错误', | |||
type: 'line', | |||
stack: '总量', | |||
data: ['0', '0', '0', '0', '0', '0', '0', '0', '2', '0', '0', '2', '2', '0', '0', '0', '0', '0', '0', '0', '0', '2', '0', '2', '2'] | |||
} | |||
] | |||
}; | |||
if (optionsone && typeof optionsone === 'object') { | |||
myChartone.setOption(optionsone); | |||
} | |||
output_list = Array(); | |||
/* level - 0:Summary; 1:Failed; 2:All */ | |||
function showCase(level) { | |||
trs = document.getElementsByTagName('tr'); | |||
for (var i = 0; i < trs.length; i++) { | |||
tr = trs[i]; | |||
id = tr.id; | |||
if (id.substr(0,2) == 'ft') { | |||
if (level < 1) { | |||
tr.className = 'hiddenRow'; | |||
} | |||
else { | |||
tr.className = ''; | |||
} | |||
} | |||
if (id.substr(0,2) == 'pt') { | |||
if (level > 1) { | |||
tr.className = ''; | |||
} | |||
else { | |||
tr.className = 'hiddenRow'; | |||
} | |||
} | |||
} | |||
} | |||
function showClassDetail(cid, count) { | |||
var id_list = Array(count); | |||
var toHide = 1; | |||
for (var i = 0; i < count; i++) { | |||
tid0 = 't' + cid.substr(1) + '.' + (i+1); | |||
tid = 'f' + tid0; | |||
tr = document.getElementById(tid); | |||
if (!tr) { | |||
tid = 'p' + tid0; | |||
tr = document.getElementById(tid); | |||
} | |||
id_list[i] = tid; | |||
if (tr.className) { | |||
toHide = 0; | |||
} | |||
} | |||
for (var i = 0; i < count; i++) { | |||
tid = id_list[i]; | |||
if (toHide) { | |||
document.getElementById('div_'+tid).style.display = 'none' | |||
document.getElementById(tid).className = 'hiddenRow'; | |||
} | |||
else { | |||
document.getElementById(tid).className = ''; | |||
} | |||
} | |||
} | |||
function showTestDetail(div_id){ | |||
var details_div = document.getElementById(div_id) | |||
var displayState = details_div.style.display | |||
if (displayState != 'block' ) { | |||
displayState = 'block' | |||
details_div.style.display = 'block' | |||
} | |||
else { | |||
details_div.style.display = 'none' | |||
} | |||
} | |||
function html_escape(s) { | |||
s = s.replace(/&/g,'&'); | |||
s = s.replace(/</g,'<'); | |||
s = s.replace(/>/g,'>'); | |||
return s; | |||
} | |||
</script> | |||
</body> | |||
</html> | |||
@@ -0,0 +1,117 @@ | |||
<!DOCTYPE html> | |||
<html> | |||
<head> | |||
<title>http接口自动化测试报告</title> | |||
<meta charset="UTF-8"> | |||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |||
<!-- 引入 Bootstrap --> | |||
<link href="https://cdn.bootcss.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"> | |||
<!-- HTML5 Shim 和 Respond.js 用于让 IE8 支持 HTML5元素和媒体查询 --> | |||
<!-- 注意: 如果通过 file:// 引入 Respond.js 文件,则该文件无法起效果 --> | |||
<!--[if lt IE 9]> | |||
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script> | |||
<script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script> | |||
<![endif]--> | |||
<style type="text/css"> | |||
.hidden-detail,.hidden-tr{ | |||
display:none; | |||
} | |||
</style> | |||
</head> | |||
<body> | |||
<div class='col-md-4 col-md-offset-4' style='margin-left:3%;'> | |||
<h1>接口测试的结果</h1> | |||
<table class="table table-hover table-condensed"> | |||
<tbody> | |||
<tr> | |||
<td><strong>开始时间:</strong> 2023-02-19 18:06:22.576639</td> | |||
</tr> | |||
<td><strong>结束时间:</strong> 2023-02-19 18:06:23.111143</td></tr> | |||
<td><strong>耗时:</strong> 0:00:00.534504</td></tr> | |||
<td><strong>结果:</strong> | |||
<span >Pass: <strong >0</strong> | |||
Fail: <strong >2</strong> | |||
exception: <strong >0</strong> | |||
weizhicuowu : <strong >0</strong></span></td> | |||
</tr> | |||
</tbody></table> | |||
</div> <div class="row " style="margin:60px"> | |||
<div style=' margin-top: 18%;' > | |||
<div class="btn-group" role="group" aria-label="..."> | |||
<button type="button" id="check-all" class="btn btn-primary">所有用例</button> | |||
<button type="button" id="check-success" class="btn btn-success">成功用例</button> | |||
<button type="button" id="check-danger" class="btn btn-danger">失败用例</button> | |||
<button type="button" id="check-warning" class="btn btn-warning">错误用例</button> | |||
<button type="button" id="check-except" class="btn btn-defult">异常用例</button> | |||
</div> | |||
<div class="btn-group" role="group" aria-label="..."> | |||
</div> | |||
<table class="table table-hover table-condensed table-bordered" style="word-wrap:break-word; word-break:break-all; margin-top: 7px;"> | |||
<tr > | |||
<td ><strong>用例ID </strong></td> | |||
<td><strong>用例名字</strong></td> | |||
<td><strong>key</strong></td> | |||
<td><strong>请求内容</strong></td> | |||
<td><strong>url</strong></td> | |||
<td><strong>请求方式</strong></td> | |||
<td><strong>预期</strong></td> | |||
<td><strong>实际返回</strong></td> | |||
<td><strong>结果</strong></td> | |||
</tr> | |||
<tr class="case-tr warning"> | |||
<td>1.0</td> | |||
<td>图灵api接口</td> | |||
<td>aaaa</td> | |||
<td>{'password':'1222'}</td> | |||
<td>/openapi/api</td> | |||
<td>POST</td> | |||
<td>code=40001</td> | |||
<td>{'code': 40007, 'text': '您的请求内容为空。'}</td> | |||
<td bgcolor="fail">fail</td> | |||
</tr> | |||
<tr class="case-tr warning"> | |||
<td>2.0</td> | |||
<td>图灵api接口</td> | |||
<td>dfeb1cc8125943d29764a2f2f5c33739</td> | |||
<td>{'password':'1222'}</td> | |||
<td>/openapi/api</td> | |||
<td>POST</td> | |||
<td>code=40002</td> | |||
<td>{'code': 40007, 'text': '您的请求内容为空。'}</td> | |||
<td bgcolor="fail">fail</td> | |||
</tr> | |||
</div></div></table><script src="https://code.jquery.com/jquery.js"></script> | |||
<script src="https://cdn.bootcss.com/bootstrap/3.3.6/js/bootstrap.min.js"></script> | |||
<script type="text/javascript"> | |||
$("#check-danger").click(function(e){ | |||
$(".case-tr").removeClass("hidden-tr"); | |||
$(".success").addClass("hidden-tr"); | |||
$(".warning").addClass("hidden-tr"); | |||
$(".error").addClass("hidden-tr"); | |||
}); | |||
$("#check-warning").click(function(e){ | |||
$(".case-tr").removeClass("hidden-tr"); | |||
$(".success").addClass("hidden-tr"); | |||
$(".danger").addClass("hidden-tr"); | |||
$(".error").addClass("hidden-tr"); | |||
}); | |||
$("#check-success").click(function(e){ | |||
$(".case-tr").removeClass("hidden-tr"); | |||
$(".warning").addClass("hidden-tr"); | |||
$(".danger").addClass("hidden-tr"); | |||
$(".error").addClass("hidden-tr"); | |||
}); | |||
$("#check-except").click(function(e){ | |||
$(".case-tr").removeClass("hidden-tr"); | |||
$(".warning").addClass("hidden-tr"); | |||
$(".danger").addClass("hidden-tr"); | |||
$(".success").addClass("hidden-tr"); | |||
}); | |||
$("#check-all").click(function(e){ | |||
$(".case-tr").removeClass("hidden-tr"); | |||
}); | |||
</script> | |||
</body></html> |
@@ -0,0 +1,10 @@ | |||
1.0: | |||
code: 0 | |||
result: | |||
code: 40007 | |||
text: 您的请求内容为空。 | |||
2.0: | |||
code: 0 | |||
result: | |||
code: 40007 | |||
text: 您的请求内容为空。 |
@@ -0,0 +1,38 @@ | |||
-----BEGIN OPENSSH PRIVATE KEY----- | |||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn | |||
NhAAAAAwEAAQAAAYEAsbthKV/+8Yu5V2R2quG1Xy6kvkZ6PcRzSoarxXh6zxoxVlyEZNXP | |||
09a9jdf1fS2l9KRaimxjr94mH4r8JGL6afyegKwPJCyjeXrjsFJMpyn4YAOs5qTMO34WbO | |||
88BSc53omDWuPvQaQFPpMK5rAs4E5c2o91tkzRks52+B2Y1wkIYFZYDBHugVgiY7B6PHQi | |||
RGoMKbuM5gvxU1zGvGumvUoUo0lXs8oLFtHpp2jZypJdlgRRGfVzfw+bD3LrfH7J6+Lse5 | |||
bZEsNB+xxRO2qQMb/2fOiP0fRXZRWX+PTkvpqNxxub7Fil8XjUY0M2W0/DG8wPAMfPxt8B | |||
ZY9ciLL+vsNobPDzsHgOxbD0+nc4XVou+RdMaAmxs8a95BGVsi0236laA/pHcMcyarCGja | |||
wJrZK+yBe+79NU45umMB9uXn7CY4j4oUX5izTHu+l9tiqpRYsmegcQMSBgDvPd/Q58kgIb | |||
WybvdOUM9OMfYeWfUXyvT84BOVVNXGGqdKrIWycDAAAFkLHO9WWxzvVlAAAAB3NzaC1yc2 | |||
EAAAGBALG7YSlf/vGLuVdkdqrhtV8upL5Gej3Ec0qGq8V4es8aMVZchGTVz9PWvY3X9X0t | |||
pfSkWopsY6/eJh+K/CRi+mn8noCsDyQso3l647BSTKcp+GADrOakzDt+FmzvPAUnOd6Jg1 | |||
rj70GkBT6TCuawLOBOXNqPdbZM0ZLOdvgdmNcJCGBWWAwR7oFYImOwejx0IkRqDCm7jOYL | |||
8VNcxrxrpr1KFKNJV7PKCxbR6ado2cqSXZYEURn1c38Pmw9y63x+yevi7HuW2RLDQfscUT | |||
tqkDG/9nzoj9H0V2UVl/j05L6ajccbm+xYpfF41GNDNltPwxvMDwDHz8bfAWWPXIiy/r7D | |||
aGzw87B4DsWw9Pp3OF1aLvkXTGgJsbPGveQRlbItNt+pWgP6R3DHMmqwho2sCa2SvsgXvu | |||
/TVOObpjAfbl5+wmOI+KFF+Ys0x7vpfbYqqUWLJnoHEDEgYA7z3f0OfJICG1sm73TlDPTj | |||
H2Hln1F8r0/OATlVTVxhqnSqyFsnAwAAAAMBAAEAAAGAQoE2IzBLioDZEo2CJgEdSAeBF7 | |||
3xgelfprRr1BF4CsTnT0SBOeYTxVXmSgxUTMnm/nr9ciyKxMUgiM8N+GOdBknD2awIYmXd | |||
qdhFGLZC/o4i5XKaoRdrYJuWsp52XAtIiS/1me4OmgZQ/BAzlQy5ThmkfxgNWPC3vvJI7C | |||
DPDy/PFZVZjvKqx3V+MMVZiAOAyw7PjFIkr/QqEiJ2Lw0tMElnHY6VJa5lpd1YTA9c54ML | |||
R9ZHrqn81L+3Kvm6ijQ6o+8k/qZ9vtDBCm062iMnL7bYlZPHAAwcmTA1j781yZVzCiw8BT | |||
6/qSc4nxq7UROks/pd8MrG+a8W/N5L+/2sP5ovWMqRMZDGG+qTwV7DHk001JKhwDzYOtHh | |||
rqmXyJpEUCtSpTNW8fuhfsbJisVyD5+VYECrPclCetPMwP5cXf5Lf/7cV4nOFo3jJkoDF7 | |||
rwDjgNC/VF/n1qAz4vw5Lp8ijj7z+uP4SPOpDYxDl8lTcXntDvf4HRarRYX59WUSChAAAA | |||
wQDWvVI9iAwme/0r/iJWoM79wlcNc+YK1i7TNlI41v720fAFKu/9AQat4dmosoPn10d+EE | |||
Vd83A4YTh3xsMGErxBxTl8twNFHcZsB1o9uO8rkTQOoRyJrDu1X8YKxav+p0IEbxeFsZyq | |||
JlPESgY19ZBMsrPyQTChowmYoGIljtspJzHcc6qrTm56vxgXnWbBHKQ5VXdlxFABAsH3d5 | |||
51dvQquQR98q348B5TD7IaEEkQRmgqYQFwwa0ApAVXgFBBP00AAADBAOyQ02MNWLdxyI66 | |||
V8F6VvTppo+DdT9N7GCZBxPQs/vZ8KcaXRGDvbW8/fLB83UH6pA3MZ8bQ5XJ7vNBsyOSgw | |||
xevFEpwz5KCxwj9JYP534tjtn89QH7tgsAjnETnrDePisUOpKVDdLm8yIhMp1/LJ5/kJj9 | |||
J3MaxEQYSlhiBmEeUl9f/JMYx9c20zp4jRAO3d2o9NOzfswgvOCqhfQ7y1xYUcNXeKjP3i | |||
k9nQLgZVWXBsq6cIPYq/P7l0AuxG/4swAAAMEAwFU7A89t6FCmr45WjwPYinkWVHe1+Ok+ | |||
MEVAW3YfPEsVPf5nb/Uvo2q6Qr8OjzqPIWS4WiPOpzYdkI2abBfo/f/sn3VzXBnpbo/wOP | |||
NHgdWPs/X1HXmohnBEAjmkGFjjvS2BZhRZ6YMimk5fOkB1qHjQ9r4FuwmiAOBdo/Mstl94 | |||
1ZZPgzARnqeS8HB0sl0lY8+pYGbGyxxBpAR5/uC6PR5XBYUPD52leir92FTby1u6JGIIhn | |||
R9HaLEgR8YyCBxAAAAE2xlaWxlaWxpMTI2QDE2My5jb20BAgMEBQYH | |||
-----END OPENSSH PRIVATE KEY----- |
@@ -0,0 +1 @@ | |||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCxu2EpX/7xi7lXZHaq4bVfLqS+Rno9xHNKhqvFeHrPGjFWXIRk1c/T1r2N1/V9LaX0pFqKbGOv3iYfivwkYvpp/J6ArA8kLKN5euOwUkynKfhgA6zmpMw7fhZs7zwFJzneiYNa4+9BpAU+kwrmsCzgTlzaj3W2TNGSznb4HZjXCQhgVlgMEe6BWCJjsHo8dCJEagwpu4zmC/FTXMa8a6a9ShSjSVezygsW0emnaNnKkl2WBFEZ9XN/D5sPcut8fsnr4ux7ltkSw0H7HFE7apAxv/Z86I/R9FdlFZf49OS+mo3HG5vsWKXxeNRjQzZbT8MbzA8Ax8/G3wFlj1yIsv6+w2hs8POweA7FsPT6dzhdWi75F0xoCbGzxr3kEZWyLTbfqVoD+kdwxzJqsIaNrAmtkr7IF77v01Tjm6YwH25efsJjiPihRfmLNMe76X22KqlFiyZ6BxAxIGAO8939DnySAhtbJu905Qz04x9h5Z9RfK9PzgE5VU1cYap0qshbJwM= leileili126@163.com |