| @@ -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原有的库进行的,这样简单方便, | |||||
| ### 使用脚本参数分离等思想,尽可能降低代码的耦合度。 | |||||
| ### 如果你不配置钉钉机器人,注释到机器人相关的代码 | |||||
| # 首先我们来看下我们的目录 | |||||
| ## | |||||
|  | |||||
| ## | |||||
| ### 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的开源项目的分享,我也运营了自己的公众号,欢迎大家关注我的公众号 | |||||
|  | |||||
| ## 产生的html测试报告如下 | |||||
|  | |||||
| ## | |||||
| ### 增加了Excel管理测试报告的功能,目前在继续优化功能,增加了config目录,一些配置文件的目录, | |||||
| ## | |||||
| ## 产生的Excel测试报告如下 | |||||
|  | |||||
|  | |||||
| ### 现在的测试结构更加完整,最新的一次提交增加了log日志的展示,使功能更加完善,log日志在控制台展示如下,对目录进行优化 | |||||
|  | |||||
| @@ -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 | |||||