commit 32724305e05b53665e21a789763dad167022d488 Author: jshixiong Date: Tue Feb 28 16:21:38 2023 +0800 commit diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..e7e9d11 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,2 @@ +# Default ignored files +/workspace.xml diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/jiekou-python3.iml b/.idea/jiekou-python3.iml new file mode 100644 index 0000000..4f2c9af --- /dev/null +++ b/.idea/jiekou-python3.iml @@ -0,0 +1,15 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..6a81379 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..eb045ae --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Interface/__init__.py b/Interface/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Interface/dubbo_feng.py b/Interface/dubbo_feng.py new file mode 100644 index 0000000..85da0a4 --- /dev/null +++ b/Interface/dubbo_feng.py @@ -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 diff --git a/Interface/testFengzhuang.py b/Interface/testFengzhuang.py new file mode 100644 index 0000000..901eff4 --- /dev/null +++ b/Interface/testFengzhuang.py @@ -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 diff --git a/Interface/test_requests.py b/Interface/test_requests.py new file mode 100644 index 0000000..ad824f0 --- /dev/null +++ b/Interface/test_requests.py @@ -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 \ No newline at end of file diff --git a/Public/BSTestRunner.py b/Public/BSTestRunner.py new file mode 100644 index 0000000..5f54424 --- /dev/null +++ b/Public/BSTestRunner.py @@ -0,0 +1,1021 @@ +""" +A TestRunner for use with the Python unit testing framework. It generates a HTML report to show the result at a glance. +The simplest way to use this is to invoke its main method. E.g. + + import unittest + import BSTestRunner + + ... define your tests ... + + if __name__ == '__main__': + BSTestRunner.main() + + +For more customization options, instantiates a BSTestRunner object. +BSTestRunner is a counterpart to unittest's TextTestRunner. E.g. + + # output to a file + fp = file('my_report.html', 'wb') + runner = BSTestRunner.BSTestRunner( + stream=fp, + title='My unit test', + description='This demonstrates the report output by BSTestRunner.' + ) + + # Use an external stylesheet. + # See the Template_mixin class for more customizable options + runner.STYLESHEET_TMPL = '' + + # run the test + runner.run(my_test_suite) + + +------------------------------------------------------------------------ +Copyright (c) 2004-2007, Wai Yip Tung +Copyright (c) 2016, Eason Han +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name Wai Yip Tung nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +""" + +__author__ = "Wai Yip Tung && Eason Han" +__version__ = "0.8.4" + +""" +Change History + +Version 0.8.3 +* Modify html style using bootstrap3. + +Version 0.8.3 +* Prevent crash on class or module-level exceptions (Darren Wurf). + +Version 0.8.2 +* Show output inline instead of popup window (Viorel Lupu). + +Version in 0.8.1 +* Validated XHTML (Wolfgang Borgert). +* Added description of test classes and test cases. + +Version in 0.8.0 +* Define Template_mixin class for customization. +* Workaround a IE 6 bug that it does not treat + %(stylesheet)s + + + + + + +
+ %(heading)s + %(report)s + %(ending)s +
+ %(scripts)s +""" + # variables: (title, generator, stylesheet, heading, report, ending) + + # ------------------------------------------------------------------------ + # Stylesheet + # + # alternatively use a for external style sheet, e.g. + # + + STYLESHEET_TMPL = """ + +""" + + # ------------------------------------------------------------------------ + # Heading + # + + HEADING_TMPL = """
+
+

%(title)s

+%(parameters)s +

%(description)s

+
+""" + HEADING_TMPL_New = """ +
+
+

%(title)s

+%(parameters)s +

%(description)s

+
+ +
+
+
+
+ """ + HEADING_OLD = """
+

%(title)s

+ %(parameters)s +

%(description)s

+
+ """ + HEADING_ATTRIBUTE_TMPL = """

%(name)s: %(value)s

+""" # variables: (name, value) + + # ------------------------------------------------------------------------ + # Report + # + + REPORT_TMPL = """ +

+公用 +失败 +所有 +

+ + + + + + + %(test_list)s + + + + + + + + + + + +
测试组/测试用例 + 数量 + 通过 + 失败 + 错误 + 查看 +
总计%(count)s%(Pass)s%(fail)s%(error)s 
+""" # variables: (test_list, count, Pass, fail, error) + + REPORT_CLASS_TMPL = r""" + + %(desc)s + %(count)s + %(Pass)s + %(fail)s + %(error)s + 详情 + +""" # variables: (style, desc, count, Pass, fail, error, cid) + + REPORT_TEST_WITH_OUTPUT_TMPL = r""" + +
%(desc)s
+ + + + + %(status)s + + + + + + +""" # variables: (tid, Class, style, desc, status) + + REPORT_TEST_NO_OUTPUT_TMPL = r""" + +
%(desc)s
+ %(status)s + +""" # variables: (tid, Class, style, desc, status) + + REPORT_TEST_OUTPUT_TMPL = r""" +%(id)s: %(output)s +""" # variables: (id, output) + + # ------------------------------------------------------------------------ + # ENDING + # + + ENDING_TMPL = """
 
""" + SCRPICTold = """ + + + + + """ + + SCRPICTDATA = r""" + + + + """ + + +# -------------------- The end of the Template class ------------------- + + +TestResult = unittest.TestResult + + +class MyResult(TestResult): + def __init__(self, verbosity=1, trynum=1): + # 默认次数是0 + TestResult.__init__(self) + self.outputBuffer = StringIO() + self.stdout0 = None + self.stderr0 = None + self.success_count = 0 + self.failure_count = 0 + self.error_count = 0 + self.verbosity = verbosity + self.trynnum = trynum + self.result = [] + self.trys = 0 # + self.istry = False + + def startTest(self, test): + TestResult.startTest(self, test) + self.stdout0 = sys.stdout + self.stderr0 = sys.stderr + + def complete_output(self): + if self.stdout0: + sys.stdout = self.stdout0 + sys.stderr = self.stderr0 + self.stdout0 = None + self.stderr0 = None + return self.outputBuffer.getvalue() + + def stopTest(self, test): + # 判断是否要重试 + if self.istry is True: + # 如果执行的次数小于重试的次数 就重试 + if self.trys < self.trynnum: + # 删除最后一个结果 + reslut = self.result.pop(-1) + # 判断结果,如果是错误就把错误的个数减掉 + # 如果是失败,就把失败的次数减掉 + if reslut[0] == 1: + self.failure_count -= 1 + else: + self.error_count -= 1 + sys.stderr.write('{}:用例正在重试中。。。'.format(test.id()) + '\n') + # 深copy用例 + test = copy.copy(test) + # 重试次数增加+1 + self.trys += 1 + # 测试 + test(self) + else: + self.istry = False + self.trys = 0 + self.complete_output() + + def addSuccess(self, test): + # 成功就不要重试 + self.istry = False + self.success_count += 1 + TestResult.addSuccess(self, test) + output = self.complete_output() + self.result.append((0, test, output, '')) + if self.verbosity > 1: + sys.stderr.write('ok ') + sys.stderr.write(str(test)) + sys.stderr.write('\n') + else: + sys.stderr.write('.') + + def addError(self, test, err): + # 重试+1,错误次数+1 + self.istry = True + self.error_count += 1 + TestResult.addError(self, test, err) + _, _exc_str = self.errors[-1] + output = self.complete_output() + self.result.append((2, test, output, _exc_str)) + if self.verbosity > 1: + sys.stderr.write('E ') + sys.stderr.write(str(test)) + sys.stderr.write('\n') + else: + sys.stderr.write('E') + + def addFailure(self, test, err): + self.istry = True + TestResult.startTestRun(self) + self.failure_count += 1 + TestResult.addFailure(self, test, err) + _, _exc_str = self.failures[-1] + output = self.complete_output() + self.result.append((1, test, output, _exc_str)) + if self.verbosity > 1: + sys.stderr.write('F ') + sys.stderr.write(str(test)) + sys.stderr.write('\n') + else: + sys.stderr.write('F') + + def stop(self) -> None: + pass + + +class _TestResult(MyResult): + # note: _TestResult is a pure representation of results. + # It lacks the output and reporting ability compares to unittest._TextTestResult. + + def __init__(self, verbosity=1, trynum=1): + TestResult.__init__(self) + super().__init__(verbosity, trynum) + + +class BSTestRunner(Template_mixin): + """ + """ + + def __init__(self, stream=sys.stdout, + verbosity=1, + title=None, + description=None, + trynum=1, + is_show=False, + filepath=""): + self.stream = stream + self.verbosity = verbosity + self.trynum = trynum + self.is_show = is_show + self.filepath = filepath + if title is None: + self.title = self.DEFAULT_TITLE + else: + self.title = title + if description is None: + self.description = self.DEFAULT_DESCRIPTION + else: + self.description = description + + self.startTime = datetime.datetime.now() + + def run(self, test): + "Run the given test case or test suite." + result = _TestResult(self.verbosity, trynum=self.trynum) + try: + test(result) + except TypeError: + pass + self.stopTime = datetime.datetime.now() + if self.is_show: + name = os.path.join(self.filepath, self.stopTime.strftime('%Y_%m_%d_%H_%M_%S') + '.txt') + with open(name, 'w+') as f: + f.write( + result.success_count.__str__() + "_" + result.error_count.__str__() + "_" + result.failure_count.__str__()) + f.close() + self.generateReport(test, result) + print('\n测试耗时: %s' % (self.stopTime - self.startTime)) + return result + + def sortResult(self, result_list): + # unittest does not seems to run in any particular order. + # Here at least we want to group them together by class. + rmap = {} + classes = [] + for n, t, o, e in result_list: + cls = t.__class__ + if not cls in rmap: + rmap[cls] = [] + classes.append(cls) + rmap[cls].append((n, t, o, e)) + r = [(cls, rmap[cls]) for cls in classes] + return r + + def getReportAttributes(self, result): + """ + Return report attributes as a list of (name, value). + Override this to add custom attributes. + """ + startTime = str(self.startTime)[:19] + duration = str(self.stopTime - self.startTime) + status = [] + if result.success_count: status.append( + '通过 %s' % result.success_count) + if result.failure_count: status.append( + '失败 %s' % result.failure_count) + if result.error_count: status.append( + '错误 %s' % result.error_count) + if status: + status = ' '.join(status) + else: + status = 'none' + return [ + ('开始时间', startTime), + ('持续时间', duration), + ('状态', status), + ] + + def generateReport(self, test, result): + report_attrs = self.getReportAttributes(result) + generator = 'BSTestRunner %s' % __version__ + stylesheet = self._generate_stylesheet() + heading = self._generate_heading(report_attrs) + report = self._generate_report(result) + ending = self._generate_ending() + if self.is_show: + scrpit = self.___generate_scrpitone() + else: + scrpit = self._generate_scrpit() + output = self.HTML_TMPL % dict( + title=saxutils.escape(self.title), + generator=generator, + stylesheet=stylesheet, + scripts=scrpit, + heading=heading, + report=report, + ending=ending + ) + self.stream.write(output.encode("utf-8")) + + def _generate_stylesheet(self): + return self.STYLESHEET_TMPL + + def _generate_heading(self, report_attrs): + ISSHOWPERDATA = True + if ISSHOWPERDATA: + a_lines = [] + for name, value in report_attrs: + line = self.HEADING_ATTRIBUTE_TMPL % dict( + name=saxutils.escape(name), ####更改 + # value = saxutils.escape(value), + + value=value, + ) + a_lines.append(line) + if self.is_show: + heading = self.HEADING_TMPL_New % dict( + title=saxutils.escape(self.title), parameters=''.join(a_lines), + description=saxutils.escape(self.description), ) + else: + heading = self.HEADING_TMPL % dict( + title=saxutils.escape(self.title), + parameters=''.join(a_lines), + description=saxutils.escape(self.description), + ) + return heading + else: + a_lines = [] + for name, value in report_attrs: + line = self.HEADING_ATTRIBUTE_TMPL % dict( + name=saxutils.escape(name), ####更改 + # value = saxutils.escape(value), + + value=value, + ) + a_lines.append(line) + heading = self.HEADING_OLD % dict( + title=saxutils.escape(self.title), + parameters=''.join(a_lines), + description=saxutils.escape(self.description), + ) + return heading + + def _generate_report(self, result): + rows = [] + sortedResult = self.sortResult(result.result) + for cid, (cls, cls_results) in enumerate(sortedResult): + # subtotal for a class + np = nf = ne = 0 + for n, t, o, e in cls_results: + if n == 0: + np += 1 + elif n == 1: + nf += 1 + else: + ne += 1 + + # format class description + if cls.__module__ == "__main__": + name = cls.__name__ + else: + name = "%s.%s" % (cls.__module__, cls.__name__) + doc = cls.__doc__ and cls.__doc__.split("\n")[0] or "" + desc = doc and '%s: %s' % (name, doc) or name + + row = self.REPORT_CLASS_TMPL % dict( + style=ne > 0 and 'text text-warning' or nf > 0 and 'text text-danger' or 'text text-success', + desc=desc, + count=np + nf + ne, + Pass=np, + fail=nf, + error=ne, + cid='c%s' % (cid + 1), + ) + rows.append(row) + + for tid, (n, t, o, e) in enumerate(cls_results): + self._generate_report_test(rows, cid, tid, n, t, o, e) + + report = self.REPORT_TMPL % dict( + test_list=''.join(rows), + count=str(result.success_count + result.failure_count + result.error_count), + Pass=str(result.success_count), + fail=str(result.failure_count), + error=str(result.error_count), + ) + return report + + def _generate_report_test(self, rows, cid, tid, n, t, o, e): + # e.g. 'pt1.1', 'ft1.1', etc + has_output = bool(o or e) + tid = (n == 0 and 'p' or 'f') + 't%s.%s' % (cid + 1, tid + 1) + name = t.id().split('.')[-1] + doc = t.shortDescription() or "" + desc = doc and ('%s: %s' % (name, doc)) or name + tmpl = has_output and self.REPORT_TEST_WITH_OUTPUT_TMPL or self.REPORT_TEST_NO_OUTPUT_TMPL + + # o and e should be byte string because they are collected from stdout and stderr? + if isinstance(o, str): + # TODO: some problem with 'string_escape': it escape \n and mess up formating + # uo = unicode(o.encode('string_escape')) + uo = o + else: + uo = o + if isinstance(e, str): + # TODO: some problem with 'string_escape': it escape \n and mess up formating + # ue = unicode(e.encode('string_escape')) + ue = e + else: + ue = e + + script = self.REPORT_TEST_OUTPUT_TMPL % dict( + id=tid, + output=saxutils.escape(uo + ue), + ) + + row = tmpl % dict( + tid=tid, + Class=(n == 0 and 'hiddenRow' or 'none'), + # Class = (n == 0 and 'hiddenRow' or 'text text-success'), + # style = n == 2 and 'errorCase' or (n == 1 and 'failCase' or 'none'), + style=n == 2 and 'text text-warning' or (n == 1 and 'text text-danger' or 'text text-success'), + desc=desc, + script=script, + status=self.STATUS[n], + ) + rows.append(row) + if not has_output: + return + + def _generate_ending(self): + return self.ENDING_TMPL + + def ___generate_scrpitone(self): + namerun, faillist, success, error = self._readresult() + return self.SCRPICTDATA % dict(reslutname=namerun, + success=success, + fail=faillist, + error=error) + + def _readresult(self): + namerun = [] + faillist = [] + success = [] + error = [] + for root, dirs, files in os.walk(self.filepath): + for file in files: + if file.endswith(".txt"): + namerun.append(file.split(".")[0].split("/")[-1]) + with open(os.path.join(root, file), 'r') as f: + reslut = f.readline().split('\n')[0].split("_") + success.append(reslut[0]) + error.append(reslut[1]) + faillist.append(reslut[2]) + return namerun, faillist, success, error + + def _generate_scrpit(self): + return self.SCRPICTold + + +############################################################################## +# Facilities for running tests from the command line +############################################################################## + +# Note: Reuse unittest.TestProgram to launch test. In the future we may +# build our own launcher to support more specific command line +# parameters like test title, CSS, etc. +class TestProgram(unittest.TestProgram): + """ + A variation of the unittest.TestProgram. Please refer to the base + class for command line parameters. + """ + + def runTests(self): + # Pick BSTestRunner as the default test runner. + # base class's testRunner parameter is not useful because it means + # we have to instantiate BSTestRunner before we know self.verbosity. + if self.testRunner is None: + self.testRunner = BSTestRunner(verbosity=self.verbosity) + unittest.TestProgram.runTests(self) + + +main = TestProgram + +############################################################################## +# Executing this module from the command line +############################################################################## diff --git a/Public/Dingtalk.py b/Public/Dingtalk.py new file mode 100644 index 0000000..945b5f2 --- /dev/null +++ b/Public/Dingtalk.py @@ -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 diff --git a/Public/__init__.py b/Public/__init__.py new file mode 100644 index 0000000..ef928eb --- /dev/null +++ b/Public/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# @Time : 2017/6/4 17:34 +# @Author : lileilei +# @Site : +# @File : __init__.py.py +# @Software: PyCharm diff --git a/Public/create_report.py b/Public/create_report.py new file mode 100644 index 0000000..3ce4a54 --- /dev/null +++ b/Public/create_report.py @@ -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('记录测试结果失败') diff --git a/Public/emmail.py b/Public/emmail.py new file mode 100644 index 0000000..946bf33 --- /dev/null +++ b/Public/emmail.py @@ -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() diff --git a/Public/fengzhuang_dict.py b/Public/fengzhuang_dict.py new file mode 100644 index 0000000..4522e7e --- /dev/null +++ b/Public/fengzhuang_dict.py @@ -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 diff --git a/Public/get_excel.py b/Public/get_excel.py new file mode 100644 index 0000000..709d125 --- /dev/null +++ b/Public/get_excel.py @@ -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 diff --git a/Public/get_excel_new.py b/Public/get_excel_new.py new file mode 100644 index 0000000..2e670eb --- /dev/null +++ b/Public/get_excel_new.py @@ -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 diff --git a/Public/log.py b/Public/log.py new file mode 100644 index 0000000..66f999a --- /dev/null +++ b/Public/log.py @@ -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 diff --git a/Public/panduan.py b/Public/panduan.py new file mode 100644 index 0000000..dea8af7 --- /dev/null +++ b/Public/panduan.py @@ -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': '填写测试预期值'} diff --git a/Public/py_Html.py b/Public/py_Html.py new file mode 100644 index 0000000..0d8b488 --- /dev/null +++ b/Public/py_Html.py @@ -0,0 +1,180 @@ +# encoding: utf-8 +""" +@author: lileilei +@file: py_Html.py +@time: 2017/6/5 17:04 +""" + +titles = '接口测试' + + +def title(titles): + title = ''' + + + %s + + + + + + + + + + + ''' % (titles) + return title + + +connent = ''' +
+

接口测试的结果

''' + + +def shouye(starttime, endtime, passge, fail, excepthions, weizhicuowu): + beijing = ''' + + + + + + + + + +
开始时间: %s
结束时间: %s
耗时: %s
结果: + Pass: %s + Fail: %s + exception: %s + weizhicuowu : %s
+
''' % (starttime, endtime, (endtime - starttime), passge, fail, excepthions, weizhicuowu) + return beijing + + +shanghai = '''
+
+
+ + + + + +
+
+
+ + + + + + + + + + + + + ''' + + +def passfail(tend): + if tend == 'pass': + htl = '''''' + elif tend == 'fail': + htl = '''''' + elif tend == 'weizhi': + htl = '''''' + else: + htl = '' + return htl + + +def ceshixiangqing(reslt, id, name, key, coneent, url, meth, yuqi, json, relust): + xiangqing = ''' + + + + + + + + + + %s + + ''' % (reslt, id, name, key, coneent, url, meth, yuqi, json, passfail(relust)) + return xiangqing + + +weibu = '''
用例ID 用例名字key请求内容url请求方式预期实际返回结果
passfailerrorexect
%s%s%s%s%s%s%s%s
+ + +''' + + +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')) diff --git a/Public/pyreport_excel.py b/Public/pyreport_excel.py new file mode 100644 index 0000000..c1e9bdd --- /dev/null +++ b/Public/pyreport_excel.py @@ -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) diff --git a/Public/test_requests.py b/Public/test_requests.py new file mode 100644 index 0000000..21ffba1 --- /dev/null +++ b/Public/test_requests.py @@ -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} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..9ea4f5e --- /dev/null +++ b/README.md @@ -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) + + + diff --git a/config/__init__.py b/config/__init__.py new file mode 100644 index 0000000..c24e270 --- /dev/null +++ b/config/__init__.py @@ -0,0 +1,5 @@ +""" +@author: lileilei +@file: __init__.py +@time: 2018/4/12 14:17 +""" diff --git a/config/config.py b/config/config.py new file mode 100644 index 0000000..c746b52 --- /dev/null +++ b/config/config.py @@ -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 # 失败重试 diff --git a/config/email.yaml b/config/email.yaml new file mode 100644 index 0000000..6fefe9a --- /dev/null +++ b/config/email.yaml @@ -0,0 +1,4 @@ +#foremail: '952943386@qq.com' +#password: "zzaikjtenujtbaif" +#toeamil: "leileili126@163.com,952943386@qq.com" +title: "测试报告" diff --git a/config/test_report.yaml b/config/test_report.yaml new file mode 100644 index 0000000..64d383a --- /dev/null +++ b/config/test_report.yaml @@ -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 diff --git a/history/2022_01_15_14_26_21.txt b/history/2022_01_15_14_26_21.txt new file mode 100644 index 0000000..3ad8fe8 --- /dev/null +++ b/history/2022_01_15_14_26_21.txt @@ -0,0 +1 @@ +2_0_0 \ No newline at end of file diff --git a/history/2022_01_16_09_36_13.txt b/history/2022_01_16_09_36_13.txt new file mode 100644 index 0000000..0fe7ef7 --- /dev/null +++ b/history/2022_01_16_09_36_13.txt @@ -0,0 +1 @@ +0_2_0 \ No newline at end of file diff --git a/history/2022_01_16_09_38_16.txt b/history/2022_01_16_09_38_16.txt new file mode 100644 index 0000000..0fe7ef7 --- /dev/null +++ b/history/2022_01_16_09_38_16.txt @@ -0,0 +1 @@ +0_2_0 \ No newline at end of file diff --git a/history/2022_01_16_09_39_12.txt b/history/2022_01_16_09_39_12.txt new file mode 100644 index 0000000..0fe7ef7 --- /dev/null +++ b/history/2022_01_16_09_39_12.txt @@ -0,0 +1 @@ +0_2_0 \ No newline at end of file diff --git a/history/2022_01_16_09_39_32.txt b/history/2022_01_16_09_39_32.txt new file mode 100644 index 0000000..0fe7ef7 --- /dev/null +++ b/history/2022_01_16_09_39_32.txt @@ -0,0 +1 @@ +0_2_0 \ No newline at end of file diff --git a/history/2022_01_16_09_39_51.txt b/history/2022_01_16_09_39_51.txt new file mode 100644 index 0000000..0fe7ef7 --- /dev/null +++ b/history/2022_01_16_09_39_51.txt @@ -0,0 +1 @@ +0_2_0 \ No newline at end of file diff --git a/history/2022_01_16_09_41_00.txt b/history/2022_01_16_09_41_00.txt new file mode 100644 index 0000000..0fe7ef7 --- /dev/null +++ b/history/2022_01_16_09_41_00.txt @@ -0,0 +1 @@ +0_2_0 \ No newline at end of file diff --git a/history/2022_01_16_09_41_37.txt b/history/2022_01_16_09_41_37.txt new file mode 100644 index 0000000..3ad8fe8 --- /dev/null +++ b/history/2022_01_16_09_41_37.txt @@ -0,0 +1 @@ +2_0_0 \ No newline at end of file diff --git a/history/2022_01_16_09_42_37.txt b/history/2022_01_16_09_42_37.txt new file mode 100644 index 0000000..3ad8fe8 --- /dev/null +++ b/history/2022_01_16_09_42_37.txt @@ -0,0 +1 @@ +2_0_0 \ No newline at end of file diff --git a/history/2022_01_16_09_43_15.txt b/history/2022_01_16_09_43_15.txt new file mode 100644 index 0000000..3ad8fe8 --- /dev/null +++ b/history/2022_01_16_09_43_15.txt @@ -0,0 +1 @@ +2_0_0 \ No newline at end of file diff --git a/history/2022_01_16_09_43_50.txt b/history/2022_01_16_09_43_50.txt new file mode 100644 index 0000000..3ad8fe8 --- /dev/null +++ b/history/2022_01_16_09_43_50.txt @@ -0,0 +1 @@ +2_0_0 \ No newline at end of file diff --git a/history/2022_01_16_09_43_56.txt b/history/2022_01_16_09_43_56.txt new file mode 100644 index 0000000..3ad8fe8 --- /dev/null +++ b/history/2022_01_16_09_43_56.txt @@ -0,0 +1 @@ +2_0_0 \ No newline at end of file diff --git a/history/2022_01_16_09_44_26.txt b/history/2022_01_16_09_44_26.txt new file mode 100644 index 0000000..3ad8fe8 --- /dev/null +++ b/history/2022_01_16_09_44_26.txt @@ -0,0 +1 @@ +2_0_0 \ No newline at end of file diff --git a/history/2022_01_16_09_44_35.txt b/history/2022_01_16_09_44_35.txt new file mode 100644 index 0000000..3ad8fe8 --- /dev/null +++ b/history/2022_01_16_09_44_35.txt @@ -0,0 +1 @@ +2_0_0 \ No newline at end of file diff --git a/history/2022_01_16_09_45_12.txt b/history/2022_01_16_09_45_12.txt new file mode 100644 index 0000000..3ad8fe8 --- /dev/null +++ b/history/2022_01_16_09_45_12.txt @@ -0,0 +1 @@ +2_0_0 \ No newline at end of file diff --git a/history/2022_01_16_09_46_33.txt b/history/2022_01_16_09_46_33.txt new file mode 100644 index 0000000..3ad8fe8 --- /dev/null +++ b/history/2022_01_16_09_46_33.txt @@ -0,0 +1 @@ +2_0_0 \ No newline at end of file diff --git a/history/2022_04_22_17_22_51.txt b/history/2022_04_22_17_22_51.txt new file mode 100644 index 0000000..3ad8fe8 --- /dev/null +++ b/history/2022_04_22_17_22_51.txt @@ -0,0 +1 @@ +2_0_0 \ No newline at end of file diff --git a/history/2022_04_22_21_06_05.txt b/history/2022_04_22_21_06_05.txt new file mode 100644 index 0000000..3ad8fe8 --- /dev/null +++ b/history/2022_04_22_21_06_05.txt @@ -0,0 +1 @@ +2_0_0 \ No newline at end of file diff --git a/history/2022_04_22_21_22_01.txt b/history/2022_04_22_21_22_01.txt new file mode 100644 index 0000000..3ad8fe8 --- /dev/null +++ b/history/2022_04_22_21_22_01.txt @@ -0,0 +1 @@ +2_0_0 \ No newline at end of file diff --git a/history/2022_04_22_21_29_08.txt b/history/2022_04_22_21_29_08.txt new file mode 100644 index 0000000..3ad8fe8 --- /dev/null +++ b/history/2022_04_22_21_29_08.txt @@ -0,0 +1 @@ +2_0_0 \ No newline at end of file diff --git a/history/2022_04_22_21_32_40.txt b/history/2022_04_22_21_32_40.txt new file mode 100644 index 0000000..3ad8fe8 --- /dev/null +++ b/history/2022_04_22_21_32_40.txt @@ -0,0 +1 @@ +2_0_0 \ No newline at end of file diff --git a/history/2023_02_19_18_06_29.txt b/history/2023_02_19_18_06_29.txt new file mode 100644 index 0000000..3ad8fe8 --- /dev/null +++ b/history/2023_02_19_18_06_29.txt @@ -0,0 +1 @@ +2_0_0 \ No newline at end of file diff --git a/history/2023_02_19_18_08_39.txt b/history/2023_02_19_18_08_39.txt new file mode 100644 index 0000000..3ad8fe8 --- /dev/null +++ b/history/2023_02_19_18_08_39.txt @@ -0,0 +1 @@ +2_0_0 \ No newline at end of file diff --git a/history/2023_02_19_18_10_30.txt b/history/2023_02_19_18_10_30.txt new file mode 100644 index 0000000..3ad8fe8 --- /dev/null +++ b/history/2023_02_19_18_10_30.txt @@ -0,0 +1 @@ +2_0_0 \ No newline at end of file diff --git a/history/2023_02_19_18_10_47.txt b/history/2023_02_19_18_10_47.txt new file mode 100644 index 0000000..3ad8fe8 --- /dev/null +++ b/history/2023_02_19_18_10_47.txt @@ -0,0 +1 @@ +2_0_0 \ No newline at end of file diff --git a/img/cebaogaotu.png b/img/cebaogaotu.png new file mode 100644 index 0000000..957379d Binary files /dev/null and b/img/cebaogaotu.png differ diff --git a/img/excel.png b/img/excel.png new file mode 100644 index 0000000..e1e09a0 Binary files /dev/null and b/img/excel.png differ diff --git a/img/excel2.png b/img/excel2.png new file mode 100644 index 0000000..e606c61 Binary files /dev/null and b/img/excel2.png differ diff --git a/img/kongzhitai.PNG b/img/kongzhitai.PNG new file mode 100644 index 0000000..c204f58 Binary files /dev/null and b/img/kongzhitai.PNG differ diff --git a/img/log.png b/img/log.png new file mode 100644 index 0000000..d64c7aa Binary files /dev/null and b/img/log.png differ diff --git a/img/weixin.png b/img/weixin.png new file mode 100644 index 0000000..52a9eb9 Binary files /dev/null and b/img/weixin.png differ diff --git a/img/xiangmujiegoutu.png b/img/xiangmujiegoutu.png new file mode 100644 index 0000000..c479bf3 Binary files /dev/null and b/img/xiangmujiegoutu.png differ diff --git a/img/xinbanbenlog.png b/img/xinbanbenlog.png new file mode 100644 index 0000000..58d9bbc Binary files /dev/null and b/img/xinbanbenlog.png differ diff --git a/img/公众号海报.jpeg b/img/公众号海报.jpeg new file mode 100644 index 0000000..5ebc961 Binary files /dev/null and b/img/公众号海报.jpeg differ diff --git a/img/新版本测试报告.png b/img/新版本测试报告.png new file mode 100644 index 0000000..d102e28 Binary files /dev/null and b/img/新版本测试报告.png differ diff --git a/log/interface_case_run-2023_02_19_18.log b/log/interface_case_run-2023_02_19_18.log new file mode 100644 index 0000000..ff63548 --- /dev/null +++ b/log/interface_case_run-2023_02_19_18.log @@ -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: 测试用例执行完毕 diff --git a/log/interface_case_run-2023_02_28_15.log b/log/interface_case_run-2023_02_28_15.log new file mode 100644 index 0000000..b4d36e7 --- /dev/null +++ b/log/interface_case_run-2023_02_28_15.log @@ -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参数信息 , {} diff --git a/result.txt b/result.txt new file mode 100644 index 0000000..015ad9d --- /dev/null +++ b/result.txt @@ -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 diff --git a/run_excel_re.py b/run_excel_re.py new file mode 100644 index 0000000..f3ffaf1 --- /dev/null +++ b/run_excel_re.py @@ -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() diff --git a/run_html.py b/run_html.py new file mode 100644 index 0000000..c60581b --- /dev/null +++ b/run_html.py @@ -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() diff --git a/run_http_html.py b/run_http_html.py new file mode 100644 index 0000000..7659219 --- /dev/null +++ b/run_http_html.py @@ -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() diff --git a/run_new.py b/run_new.py new file mode 100644 index 0000000..7cab23e --- /dev/null +++ b/run_new.py @@ -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) diff --git a/testCase/__init__.py b/testCase/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/testCase/case.py b/testCase/case.py new file mode 100644 index 0000000..a2ee96f --- /dev/null +++ b/testCase/case.py @@ -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 diff --git a/testCase/ddt_case.py b/testCase/ddt_case.py new file mode 100644 index 0000000..ffaf560 --- /dev/null +++ b/testCase/ddt_case.py @@ -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='预期和返回不一致') diff --git a/testCase/dubbocase.py b/testCase/dubbocase.py new file mode 100644 index 0000000..eb91ee1 --- /dev/null +++ b/testCase/dubbocase.py @@ -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 diff --git a/testCase/pytestCasetest.py b/testCase/pytestCasetest.py new file mode 100644 index 0000000..e07d16f --- /dev/null +++ b/testCase/pytestCasetest.py @@ -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) diff --git a/test_Report/2023-0219.html b/test_Report/2023-0219.html new file mode 100644 index 0000000..ced4e18 --- /dev/null +++ b/test_Report/2023-0219.html @@ -0,0 +1,264 @@ + + + + + + + + 报告 + + + + + + + + + + + + +
+ +
+
+

报告

+

开始时间: 2023-02-19 18:10:47

+

持续时间: 0:00:00.099009

+

状态: 通过 2

+ +

测试报告

+
+ +
+
+
+
+ + +

+公用 +失败 +所有 +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
测试组/测试用例 + 数量 + 通过 + 失败 + 错误 + 查看 +
testCase.ddt_case.MyTest2200详情
test_api_1: 1.处理参数
通过
test_api_2: 1.处理参数
通过
总计2200 
+ +
 
+
+ + + + + diff --git a/test_Report/20230219-result.xls b/test_Report/20230219-result.xls new file mode 100644 index 0000000..de4be40 Binary files /dev/null and b/test_Report/20230219-result.xls differ diff --git a/test_Report/202302191806-result.html b/test_Report/202302191806-result.html new file mode 100644 index 0000000..cd896e2 --- /dev/null +++ b/test_Report/202302191806-result.html @@ -0,0 +1,117 @@ + + + + http接口自动化测试报告 + + + + + + + + + + + +
+

接口测试的结果

+ + + + + + + + + +
开始时间: 2023-02-19 18:06:22.576639
结束时间: 2023-02-19 18:06:23.111143
耗时: 0:00:00.534504
结果: + Pass: 0 + Fail: 2 + exception: 0 + weizhicuowu : 0
+
+
+
+ + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
用例ID 用例名字key请求内容url请求方式预期实际返回结果
1.0图灵api接口aaaa{'password':'1222'}/openapi/apiPOSTcode=40001{'code': 40007, 'text': '您的请求内容为空。'}fail
2.0图灵api接口dfeb1cc8125943d29764a2f2f5c33739{'password':'1222'}/openapi/apiPOSTcode=40002{'code': 40007, 'text': '您的请求内容为空。'}fail
+ + + \ No newline at end of file diff --git a/test_Report/20230228-result.xls b/test_Report/20230228-result.xls new file mode 100644 index 0000000..edf99de Binary files /dev/null and b/test_Report/20230228-result.xls differ diff --git a/test_Report/caseresult.yaml b/test_Report/caseresult.yaml new file mode 100644 index 0000000..96923ae --- /dev/null +++ b/test_Report/caseresult.yaml @@ -0,0 +1,10 @@ +1.0: + code: 0 + result: + code: 40007 + text: 您的请求内容为空。 +2.0: + code: 0 + result: + code: 40007 + text: 您的请求内容为空。 diff --git a/test_case_data/case.xlsx b/test_case_data/case.xlsx new file mode 100644 index 0000000..6e41bf3 Binary files /dev/null and b/test_case_data/case.xlsx differ diff --git a/test_case_data/dubbocase.xlsx b/test_case_data/dubbocase.xlsx new file mode 100644 index 0000000..f20e1df Binary files /dev/null and b/test_case_data/dubbocase.xlsx differ diff --git a/yesy b/yesy new file mode 100644 index 0000000..4696273 --- /dev/null +++ b/yesy @@ -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----- diff --git a/yesy.pub b/yesy.pub new file mode 100644 index 0000000..f1357db --- /dev/null +++ b/yesy.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCxu2EpX/7xi7lXZHaq4bVfLqS+Rno9xHNKhqvFeHrPGjFWXIRk1c/T1r2N1/V9LaX0pFqKbGOv3iYfivwkYvpp/J6ArA8kLKN5euOwUkynKfhgA6zmpMw7fhZs7zwFJzneiYNa4+9BpAU+kwrmsCzgTlzaj3W2TNGSznb4HZjXCQhgVlgMEe6BWCJjsHo8dCJEagwpu4zmC/FTXMa8a6a9ShSjSVezygsW0emnaNnKkl2WBFEZ9XN/D5sPcut8fsnr4ux7ltkSw0H7HFE7apAxv/Z86I/R9FdlFZf49OS+mo3HG5vsWKXxeNRjQzZbT8MbzA8Ax8/G3wFlj1yIsv6+w2hs8POweA7FsPT6dzhdWi75F0xoCbGzxr3kEZWyLTbfqVoD+kdwxzJqsIaNrAmtkr7IF77v01Tjm6YwH25efsJjiPihRfmLNMe76X22KqlFiyZ6BxAxIGAO8939DnySAhtbJu905Qz04x9h5Z9RfK9PzgE5VU1cYap0qshbJwM= leileili126@163.com