def test_run(request): """ 运行用例 :param request: :return: """ kwargs = { "failfast": False, } runner = HttpRunner(**kwargs) testcase_dir_path = os.path.join(os.getcwd(), "suite") testcase_dir_path = os.path.join(testcase_dir_path, get_time_stamp()) if request.is_ajax(): kwargs = json.loads(request.body.decode('utf-8')) id = kwargs.pop('id') base_url = kwargs.pop('env_name') type = kwargs.pop('type') run_test_by_type(id, base_url, testcase_dir_path, type) report_name = kwargs.get('report_name', None) main_hrun.delay(testcase_dir_path, report_name) return HttpResponse('用例执行中,请稍后查看报告即可,默认时间戳命名报告') else: id = request.POST.get('id') base_url = request.POST.get('env_name') type = request.POST.get('type', 'test') run_test_by_type(id, base_url, testcase_dir_path, type) runner.run(testcase_dir_path) #shutil.rmtree(testcase_dir_path) summary = timestamp_to_datetime(runner._summary, type=False) print(summary) return render(request, 'report_template.html', summary)
def runTestCase(self): runner = HttpRunner(failfast=False) summary = {} for path in self.needRunCase: runner.run(path, mapping=self.__mapping) if (len(summary) == 0): summary = runner.summary else: summary['time']['duration'] += runner.summary['time'][ 'duration'] summary['stat']['teststeps']['total'] += runner.summary[ 'stat']['teststeps']['total'] summary['stat']['teststeps']['successes'] += runner.summary[ 'stat']['teststeps']['successes'] summary['stat']['teststeps']['failures'] += runner.summary[ 'stat']['teststeps']['failures'] summary['stat']['teststeps']['errors'] += runner.summary[ 'stat']['teststeps']['errors'] summary['stat']['teststeps']['skipped'] += runner.summary[ 'stat']['teststeps']['skipped'] for each in runner.summary['details']: summary['details'].append(each) pass self.summary = parse_summary(summary)
def debug_api(api, project, name=None, config=None, save=True): """debug api api :dict or list project: int """ if len(api) == 0: return TEST_NOT_EXISTS # testcases if isinstance(api, dict): """ httprunner scripts or teststeps """ api = [api] testcase_list = [ parse_tests(api, load_debugtalk(project), name=name, config=config) ] kwargs = {"failfast": False} runner = HttpRunner(**kwargs) runner.run(testcase_list) summary = parse_summary(runner.summary) if save: save_summary("", summary, project, type=1) return summary
def debug_cases(cases, config=None, debugtalk=None, project_mapping=None): """ :param cases: [ {case_name:'', case_steps:[]}, {}] :param config: :param debugtalk: :param project_mapping: :return:s """ if len(cases) == 0 or not isinstance(cases, list): return "error! this case no steps" cases_list = [] for case in cases: testset = parse_case(case['case_steps'], case['case_name'], config, debugtalk) cases_list.append(testset) testcases = { "project_mapping": { "PWD": "", "functions": {}, "variables": {}, "env": {} }, 'testcases': cases_list } kwargs = {"failfast": False} runner = HttpRunner(**kwargs) runner.run(testcases) summary = runner.summary return summary
def test_log_file(self): log_file_path = os.path.join(os.getcwd(), 'reports', "test_log_file.log") runner = HttpRunner(failfast=True, log_file=log_file_path) runner.run(self.testcase_cli_path) self.assertTrue(os.path.isfile(log_file_path)) os.remove(log_file_path)
def project_hrun(name, base_url, project): """ 异步运行整个项目 :param env_name: str: 环境地址 :param project: str :return: """ kwargs = { "failfast": False, } runner = HttpRunner(**kwargs) id = Project.objects.get(project_name=project).id testcase_dir_path = os.path.join(os.getcwd(), "suite") testcase_dir_path = os.path.join(testcase_dir_path, get_time_stamp()) run_by_project(id, base_url, testcase_dir_path) runner.run(testcase_dir_path) shutil.rmtree(testcase_dir_path) summary = timestamp_to_datetime(runner.summary) report_path = add_test_reports(summary, report_name=name) os.remove(report_path)
def suite_hrun(name, base_url, suite): """ 异步运行模块 :param env_name: str: 环境地址 :param project: str:项目所属模块 :param module: str:模块名称 :return: """ logger.setup_logger('INFO') kwargs = { "failfast": False, } runner = HttpRunner(**kwargs) suite = list(suite) testcase_dir_path = os.path.join(os.getcwd(), "suite") testcase_dir_path = os.path.join(testcase_dir_path, get_time_stamp()) try: for value in suite: run_by_suite(value[0], base_url, testcase_dir_path) except ObjectDoesNotExist: return '找不到Suite信息' runner.run(testcase_dir_path) shutil.rmtree(testcase_dir_path) runner.summary = timestamp_to_datetime(runner.summary) report_path = add_test_reports(runner, report_name=name) os.remove(report_path)
def project_hrun(name, base_url, project, receiver): """ 异步运行整个项目 :param env_name: str: 环境地址 :param project: str :return: """ logger.setup_logger('INFO') kwargs = { "failfast": False, } runner = HttpRunner(**kwargs) id = ProjectInfo.objects.get(project_name=project).id testcase_dir_path = os.path.join(os.getcwd(), "suite") testcase_dir_path = os.path.join(testcase_dir_path, get_time_stamp()) run_by_project(id, base_url, testcase_dir_path) runner.run(testcase_dir_path) shutil.rmtree(testcase_dir_path) runner._summary = timestamp_to_datetime(runner._summary) report_path = add_test_reports(runner, report_name=name) if receiver != '': send_email_reports(receiver, report_path) os.remove(report_path)
def debug_suite(suite, project, obj, config=None, save=True): """debug suite suite :list pk: int project: int """ if len(suite) == 0: return TEST_NOT_EXISTS debugtalk = load_debugtalk(project) test_sets = [] for index in range(len(suite)): # copy.deepcopy 修复引用bug testcases = copy.deepcopy( parse_tests(suite[index], debugtalk, name=obj[index]['name'], config=config)) test_sets.append(testcases) kwargs = {"failfast": False} runner = HttpRunner(**kwargs) runner.run(test_sets) summary = parse_summary(runner.summary) if save: save_summary("", summary, project, type=1) return summary
def run_case(self): scheduler.app.logger.info('测试数据:{}'.format(self.TEST_DATA)) # res = main_ate(self.TEST_DATA) runner = HttpRunner() runner.run(self.TEST_DATA) jump_res = json.dumps(runner._summary, ensure_ascii=False, default=encode_object, cls=JSONEncoder) # scheduler.app.logger.info('返回数据:{}'.format(jump_res)) return jump_res
def run_test(request): """ 运行用例 :param request: :return: """ kwargs = { "failfast": False, } runner = HttpRunner(**kwargs) testcase_dir_path = os.path.join(settings.BASE_DIR, "suite") testcase_dir_path = os.path.join(testcase_dir_path, get_time_stamp()) account = request.session["now_account"] if request.is_ajax(): kwargs = json.loads(request.body.decode('utf-8')) id = kwargs.pop('id') suite_name = TestSuite.objects.get(id=id).suite_name cfg_id = kwargs.pop('cfg_id') base_url = kwargs.pop('env_name') type = kwargs.pop('type') run_test_by_type(id, base_url, testcase_dir_path, type, cfg_id) report_name = kwargs.get('report_name', None) request.session["base_url"] = base_url request.session["cfg_id"] = cfg_id main_hrun.delay(testcase_dir_path, report_name) return HttpResponse('用例执行中,请稍后查看报告即可,默认时间戳命名报告') else: id = request.POST.get('id') base_url = request.POST.get('env_name') type = request.POST.get('type', 'test') cfg_id = request.POST.get('cfg_id') request.session["base_url"] = base_url request.session["cfg_id"] = cfg_id run_test_by_type(id, base_url, testcase_dir_path, type, cfg_id) if type == "suite": suite_name = TestSuite.objects.get(id=id).suite_name runner.run( os.path.join(testcase_dir_path, "{}.yml".format(suite_name))) else: runner.run(testcase_dir_path) #删除yml文件,异常的时候不删除,可以用来debug shutil.rmtree(testcase_dir_path) runner._summary = timestamp_to_datetime(runner.summary, type=False) #data = request.body.decode('utf-8') # kwargs = json.loads(request.body.decode('utf-8')) #report_name = kwargs.get('report_name', None) report_name = get_test_name(id, type) report_id = add_test_reports(runner, account, report_name) if request.POST.get('account') == "Jenkins": result = download_report(request, report_id) return result else: runner.summary.setdefault("report_id", report_id) return render_to_response('report_template.html', runner.summary)
async def post(self, request): host = await models.HostIP.filter(name=request.json.get("host") ).first() config = await models.Config.filter(name=request.json.get("config") ).first() name = request.json.get("name") back_async = request.json.get("async") relation = request.json.get("relation") pro = await models.Project.filter(pk=request.json.get("project") ).first() config_body = {} if request.json.get("config") == "请选择" else eval( config.body) test_case = [] if host != "请选择": host = await models.HostIP.get(name=host, project=pro) for relation_id in relation: api = await models.API.filter( project=request.json.get("project"), relation=relation_id).order_by("id").values("body") for content in api: api = eval(content['body']) data = { "project_mapping": { "PWD": "", "functions": {}, "env": {} }, "testcases": [] } test_struct = {"config": config_body, "teststeps": [api]} data["testcases"].append(test_struct) runner = HttpRunner(failfast=False) runner.run(data) if back_async: summary = loader.TEST_NOT_EXISTS summary["msg"] = "接口运行中,请稍后查看报告" else: summary = runner.summary result = { "name": summary["time"]["start_datetime"], "type": 1, "summary": [summary], "project": pro } await models.Report.create(**result) return resp_json(msg="报告添加成功!")
def test_html_report(self): report_save_dir = os.path.join(os.getcwd(), 'reports', "demo") runner = HttpRunner(failfast=True, report_dir=report_save_dir) runner.run(self.testcase_cli_path) summary = runner.summary self.assertEqual(summary["stat"]["testcases"]["total"], 1) self.assertEqual(summary["stat"]["teststeps"]["total"], 10) self.assertEqual(summary["stat"]["teststeps"]["skipped"], 4) self.assertGreater(len(os.listdir(report_save_dir)), 0) shutil.rmtree(report_save_dir)
def hookFunction(testcase_path, variables): testcase_path = os.path.join(os.getcwd(), testcase_path) runner = HttpRunner(failfast=True) tests_mapping = loader.load_tests(testcase_path) # to add variables into tests_mapping.teststeps tests_mapping['apis'][0]['variables'] = variables parsed_tests_mapping = parser.parse_tests(tests_mapping) runner.run(parsed_tests_mapping)
def generate_cookies(): if (not os.path.exists(COOKIES_PATH)) or ( 3600 < int(time.time()) - int(os.path.getmtime(COOKIES_PATH))) or ( os.path.getsize(COOKIES_PATH) == 0): # cookies 文件不存在 或 最后修改时间超过 3600 秒 (1小时) 或 cookie文件内容为空 则重新登录刷新 cookies runner = HttpRunner() runner.run(r'api/login.yml') with open(COOKIES_PATH, 'r') as f: cookies: str = f.read() print("读取文件内cookie" + cookies) return cookies
def test_html_report_with_fixed_report_file(self): report_save_dir = os.path.join(os.getcwd(), 'reports', "demo") report_file = 'test.html' runner = HttpRunner(failfast=True, report_dir=report_save_dir, report_file=report_file) runner.run(self.testcase_cli_path) summary = runner.summary self.assertEqual(summary["stat"]["testcases"]["total"], 1) self.assertEqual(summary["stat"]["teststeps"]["total"], 10) self.assertEqual(summary["stat"]["teststeps"]["skipped"], 4) self.assertEqual(len(os.listdir(report_save_dir)), 1) self.assertTrue(os.path.isfile(os.path.join(report_save_dir, report_file))) shutil.rmtree(report_save_dir)
async def get(self, request): host = await models.HostIP.filter(name=self.request.args.get("host") ).first() name = self.request.args.get("name") pro = self.request.args.get("project") test_list = await models.CaseStep.filter( case_id__in=self.request.args.get("id") ).order_by("step").values("body") test_case = [] config = {} if host != "请选择": host = await models.HostIP.filter(name=host, project=pro) for content in test_list: body = eval(content["body"]) if "base_url" in body["request"]: config = await models.Config.filter( name=body["name"], project=request.json.get("project")) continue test_case.append(parse_host(host, body)) data = { "project_mapping": { "PWD": "", "functions": {}, "env": {} }, "testcases": [] } test_struct = {"config": config, "teststeps": test_case} data["testcases"].append(test_struct) runner = HttpRunner(failfast=False) runner.run(data) summary = runner.summary result = { "name": summary["time"]["start_datetime"], "type": 1, "summary": [summary], "project": pro } await models.Report.create(**result) return resp_json(msg="报告添加成功!")
def test_html_report_repsonse_image(self): runner = HttpRunner(failfast=True) summary = runner.run("tests/httpbin/load_image.yml") report_save_dir = os.path.join(os.getcwd(), 'reports', "demo") report_path = report.gen_html_report(summary, report_dir=report_save_dir) self.assertTrue(os.path.isfile(report_path)) shutil.rmtree(report_save_dir)
def run_batch_test(request): """ 批量运行用例 :param request: :return: """ kwargs = { "failfast": False, } runner = HttpRunner(**kwargs) testcase_dir_path = os.path.join(settings.BASE_DIR, "suite") testcase_dir_path = os.path.join(testcase_dir_path, get_time_stamp()) if request.is_ajax(): kwargs = json.loads(request.body.decode('utf-8')) test_list = kwargs.pop('id') base_url = kwargs.pop('env_name') cfg_id = kwargs.pop('cfg_id') type = kwargs.pop('type') report_name = kwargs.get('report_name', None) run_by_batch(test_list, base_url, testcase_dir_path, cfg_id, type=type) main_hrun.delay(testcase_dir_path, report_name) return HttpResponse('用例执行中,请稍后查看报告即可,默认时间戳命名报告') else: type = request.POST.get('type', None) base_url = request.POST.get('env_name') test_list = request.body.decode('utf-8').split('&') cfg_id = request.POST.get('cfg_id') if type: run_by_batch(test_list, base_url, testcase_dir_path, cfg_id, type=type, mode=True) else: run_by_batch(test_list, base_url, testcase_dir_path, cfg_id) runner.run(testcase_dir_path) shutil.rmtree(testcase_dir_path) runner.summary = timestamp_to_datetime(runner.summary, type=False) return render_to_response('report_template.html', runner.summary)
def main_hrun(testset_path, report_name): """ 用例运行 :param testset_path: dict or list :param report_name: str :return: """ logger.setLevel('INFO') kwargs = { "failfast": False, } runner = HttpRunner(**kwargs) runner.run(testset_path) #shutil.rmtree(testset_path) summary = timestamp_to_datetime(runner.summary) report_path = add_test_reports(summary, report_name=report_name) os.remove(report_path)
class RunCaseAndUpload(object): def __init__(self, **kwargs): self.runner = HttpRunner() self.summary = self._runTestCase() self.section = kwargs.get('section') self.build_id = kwargs.get('buildId') # noinspection SpellCheckingInspection def _runTestCase(self, dot_env_path=None, maping=None): """ Run the test case in the specified directory based on the parameters. :param dot_env_path: Empty runs the default environment, otherwise the corresponding environment :param maping: ignore :return: test case result. """ path = getConfigValue(self.section, 'autoTest.casePath') if not path: print("test path nonentity or not find files 'properties.ini'") raise FileNotFoundError elif os.getenv("TEST_ENV") == 'txy': self.runner.run(path, dot_env_path=dot_env_path, mapping=maping) return self.runner.summary elif os.getenv("TEST_ENV") == 'docker': self.runner.run(path, dot_env_path='doc.env', mapping=maping) return self.runner.summary def uploadDataToStargazing(self): """ Processing is completed the processing of the results will be uploaded to stargazing platform. :return: """ headers = {'Content-Type': 'application/json'} url = getConfigValue('stargazing', 'total') data = dataManipulation(self.summary, self.section, buildId=self.build_id) # noinspection PyBroadException try: response = requests.post(url, json=data, headers=headers) print("upload success: {}".format( response.json() if response.status_code == 200 else "upload failed:", response.content)) except Exception as e: print(f'Upload Exception:{e}')
async def get(self, request): api = await models.API.filter(id=self.request.args.get("id")).first() config = await models.Config.filter( name=self.request.args.get("config")).first() pro = await models.Project.filter(pk=api.project_id).first() debug_talk = await models.DebugTalk.filter(project_id=api.project_id ).first() variables = await models.Variables.filter(project_id=api.project_id ).values("key", "value") config_body = {} if self.request.args.get("config") == "请选择" else eval( config.body) data = { "project_mapping": { "PWD": "", "functions": {}, "env": {} }, "testcases": [] } test_struct = {"config": config_body, "teststeps": [eval(api.body)]} data["testcases"].append(test_struct) runner = HttpRunner(failfast=False) runner.run(data) summary = runner.summary result = { "name": summary["time"]["start_datetime"], "type": 1, "summary": [summary], "project": pro } await models.Report.create(**result) return resp_json(msg="报告添加成功!")
def run_test(request): """ 运行用例 :param request: :return: """ kwargs = { "failfast": False, } runner = HttpRunner(**kwargs) testcase_dir_path = os.path.join(os.getcwd(), "suite") testcase_dir_path = os.path.join(testcase_dir_path, get_time_stamp()) if request.is_ajax(): kwargs = json.loads(request.body.decode('utf-8')) id = kwargs.pop('id') base_url = kwargs.pop('env_name') type = kwargs.pop('type') run_test_by_type(id, base_url, testcase_dir_path, type) report_name = kwargs.get('report_name', None) main_hrun.delay(testcase_dir_path, report_name) return HttpResponse('用例执行中,请稍后查看报告即可,默认时间戳命名报告') else: id = request.POST.get('id') base_url = request.POST.get('env_name') type = request.POST.get('type', 'test') testcase_dir_path1 = os.path.join(testcase_dir_path, 'guest项目') run_test_by_type(id, base_url, testcase_dir_path, type) runner.run(testcase_dir_path1) # shutil.rmtree(testcase_dir_path) # 递归删除所有文件 runner._summary = timestamp_to_datetime(runner._summary, base_url, type=False) with open('summary.json', 'w', encoding='utf-8') as f: json.dump(runner._summary, f, ensure_ascii=False, sort_keys=True, indent=4) return render_to_response('report_template.html', runner._summary)
def runtestcase(self, test_path=None, report_title=None, **kwargs): buildId = os.environ.get('BUILD_ID', '') templatePath = os.path.join(os.path.dirname(os.path.dirname(__file__)), "templates", "report_template.html") runner = HttpRunner(failfast=False, log_level=self.log_level, log_file=None) #,report_template=templatePath) runner.run(test_path) runner._summary['html_report_name'] = report_title report.gen_html_report(runner._summary, report_template=templatePath) # #修改原生框架生成的报告名 start_datetime = runner._summary["time"]["start_datetime"] start_at_timestamp = str( runner._summary["time"]["start_at"]).split('.')[0] report_file_name = "{}.html".format( start_datetime.replace(":", "").replace("-", "")) report_dir = os.path.join(os.getcwd(), "reports") reporttime = RunTime().getToDateTime(int(start_at_timestamp), "%Y-%m-%d_%H_%M_%S") report_file = os.path.join(report_dir, report_file_name) if os.path.exists(report_file): if buildId: self.reportName = report_title + "{}.html".format(buildId) reportpath = os.path.join(report_dir, self.reportName) else: reportpath = os.path.join( report_dir, report_title + "{}.html".format(str(reporttime))) os.rename(report_file, reportpath) self.summary = runner._summary args = kwargs.get('args') if args and args.testType == TEST_TYPE_1: fail = self.summary.get("stat").get('testcases').get('fail', 0) if fail > 0 and buildId: fail_dir = os.path.join(os.getcwd(), "failReports") if not os.path.exists(fail_dir): os.mkdir(fail_dir) shutil.copy(reportpath, fail_dir) return self.summary
def run(): runner = HttpRunner(failfast=False, log_level='INFO') run_report_path = r"reports/" + time.strftime('%Y%m%d%H%M%S') + ".html" # 2、运行用例 # run方法支持如下参数: # yml用例文件的路径 # 字典(用例的信息) # runner.run('testsuites/') # gen_html_report(runner._summary, report_template="templates/extent-theme-template.html") summary = runner.run(r'testsuites', dot_env_path='conf/env/.online_zy.env') gen_html_report(summary, report_file=run_report_path) print("报告地址:", os.path.abspath('.') + '/' + run_report_path)
def test_run(request): """ 运行用例 :param request: :return: """ test_run kwargs = { "failfast": False, } runner = HttpRunner(**kwargs) testcase_dir_path = os.path.join(os.getcwd(), "suite") testcase_dir_path = os.path.join(testcase_dir_path, get_time_stamp()) if request.is_ajax(): kwargs = json.loads(request.body.decode('utf-8')) id = kwargs.pop('id') base_url = kwargs.pop('env_name') type = kwargs.pop('type') run_test_by_type(id, base_url, testcase_dir_path, type) report_name = kwargs.get('report_name', None) main_hrun.delay(testcase_dir_path, report_name) return HttpResponse('用例执行中,请稍后查看报告即可,默认时间戳命名报告') else: id = request.POST.get('id') base_url = request.POST.get('env_name') type = request.POST.get('type', 'test') run_test_by_type(id, base_url, testcase_dir_path, type) # 最终把该测试用例的数据生成目录下的yml文件hat\suite\2020-06-02 15-13-31-748 runner.run(testcase_dir_path) #运行该路径的yml文件 suite\2020-06-02 15-13-31-748\CAS\getuser\getuser_1.yml #shutil.rmtree(testcase_dir_path) summary = timestamp_to_datetime(runner._summary, type=False) #runner._summary是运行结果 #print(summary) return render(request,'report_template.html', summary) #渲染到模板,显示报告
def run_testsuit_by_suit_id(suit_id, user): data = TestSuit.get_content_by_suit_id(suit_id) suit_content = data.get('suit_content') project_id = data.get('project_id') case_id_env_id_list = [] for content in suit_content: case_id_env_id_list.append({ 'exec_id': content.get('exec_id'), 'env_id': content.get('env_id') }) test_suit_parse = case_handle.TestSuitParse(case_id_env_id_list, project_id) suite = test_suit_parse.get_httprunner_test_suite_json() runner = HttpRunner() result = runner.run(suite) report_save_path = os.path.join(os.getcwd(), 'openapi/reports') report_path = report.gen_html_report(result, report_dir=report_save_path) Report.create(report_path, suit_id, user) return report_path.split('/')[-1]
def run_testcase(testcase_dir, report_name): """ 利用HttpRunner执行用例并将相关数据存储到数据库 :param report_name: 报告名称 :param testcase_dir: 需要执行的目录 :return: 返回生成 报告数据 ID """ # 创建HttpRunner对象 runner = HttpRunner() try: summary = runner.run(testcase_dir) except ParamsError: logger.error("用例参数有误") data = { "msg": "用例参数有误" } return Response(data, status=400) summary = timestamp_to_datetime(summary, type=False) report_id = create_report(summary, report_name) return Response({ "id": report_id }, status=status.HTTP_201_CREATED)
def suite_hrun(name, base_url, suite, receiver): """ 异步运行模块 :param env_name: str: 环境地址 :param project: str:项目所属模块 :param module: str:模块名称 :return: """ logger.setup_logger('INFO') kwargs = { "failfast": False, } runner = HttpRunner(**kwargs) suite = list(suite) testcase_dir_path = os.path.join(os.getcwd(), "suite") testcase_dir_path = os.path.join(testcase_dir_path, get_time_stamp()) try: for value in suite: run_by_suite(value[0], base_url, testcase_dir_path) except ObjectDoesNotExist: return '找不到Suite信息' # runner.run(testcase_dir_path) runner.summary = runner.run(testcase_dir_path) shutil.rmtree(testcase_dir_path) runner.summary = timestamp_to_datetime(runner.summary) # report_path = add_test_reports(runner, report_name=name) report_result = add_test_reports(runner, report_name=name) report_path, report_id = report_result[0], report_result[1] # 处理报告结果失败,发送失败主题邮件 if not runner.summary.get('success', None): FailName = [] for i in runner.summary.get('details'): if i.get('success') == False: FailName.append(i.get('name')) # subjects = "定时任务出现错误情况预警通知" status = "【 失败 】" bodyText = "{}定时任务执行失败用例如下:<br>  {} <br> 请套件相关维护人员及时确认!!!".format( name, '<br>  '.join(FailName)) send_email_reports(receiver, report_path, name=name, bodyText=bodyText, status=status) os.remove(report_path) # 调用dingding机器人发送失败通知 bodyText = "{}定时任务执行失败用例如下:\n {}\n如需了解更多内容,请关注邮箱中邮件!".format( name, '\n '.join(FailName)) callDingTalkRobot(name, bodyText) return "" # 处理接口响应时长超时,发送告警邮件 timeOut_result = statistics_summary_timeOut(runner.summary) if timeOut_result: status = "【 告警 】" bodyText = "{0}定时任务执行接口时长告警用例如下: {1}".format( name, write_htmlTable(timeOut_result)) # 创建bug createrZentaoBug(suite[0], timeOut_result, report_id=report_id) send_email_reports(receiver, report_path, name=name, bodyText=bodyText, status=status) if receiver != '': send_email_reports(receiver, report_path, name=name) os.remove(report_path)
class TestHttpRunner(ApiServerUnittest): def setUp(self): self.testcase_cli_path = "tests/data/demo_testcase_cli.yml" self.testcase_file_path_list = [ os.path.join( os.getcwd(), 'tests/data/demo_testcase_hardcode.yml'), os.path.join( os.getcwd(), 'tests/data/demo_testcase_hardcode.json') ] testcases = [{ 'config': { 'name': 'testcase description', 'request': { 'base_url': '', 'headers': {'User-Agent': 'python-requests/2.18.4'} }, 'variables': [] }, "teststeps": [ { 'name': '/api/get-token', 'request': { 'url': 'http://127.0.0.1:5000/api/get-token', 'method': 'POST', 'headers': {'Content-Type': 'application/json', 'app_version': '2.8.6', 'device_sn': 'FwgRiO7CNA50DSU', 'os_platform': 'ios', 'user_agent': 'iOS/10.3'}, 'json': {'sign': '9c0c7e51c91ae963c833a4ccbab8d683c4a90c98'} }, 'extract': [ {'token': 'content.token'} ], 'validate': [ {'eq': ['status_code', 200]}, {'eq': ['headers.Content-Type', 'application/json']}, {'eq': ['content.success', True]} ] }, { 'name': '/api/users/1000', 'request': { 'url': 'http://127.0.0.1:5000/api/users/1000', 'method': 'POST', 'headers': {'Content-Type': 'application/json', 'device_sn': 'FwgRiO7CNA50DSU','token': '$token'}, 'json': {'name': 'user1', 'password': '******'} }, 'validate': [ {'eq': ['status_code', 201]}, {'eq': ['headers.Content-Type', 'application/json']}, {'eq': ['content.success', True]}, {'eq': ['content.msg', 'user created successfully.']} ] } ] }] self.tests_mapping = { "testcases": testcases } self.runner = HttpRunner(failfast=True) self.reset_all() def reset_all(self): url = "%s/api/reset-all" % self.host headers = self.get_authenticated_headers() return self.api_client.get(url, headers=headers) def test_text_run_times(self): summary = self.runner.run(self.testcase_cli_path) self.assertEqual(summary["stat"]["testcases"]["total"], 1) self.assertEqual(summary["stat"]["teststeps"]["total"], 10) def test_text_run_times_invalid(self): testcases = [ { "config": { 'name': "post data", 'variables': [] }, "teststeps": [ { "name": "post data", "times": "1.5", "request": { "url": "{}/post".format(HTTPBIN_SERVER), "method": "POST", "headers": { "User-Agent": "python-requests/2.18.4", "Content-Type": "application/json" }, "data": "abc" }, "validate": [ {"eq": ["status_code", 200]} ] } ] } ] tests_mapping = { "testcases": testcases } with self.assertRaises(exceptions.ParamsError): self.runner.run_tests(tests_mapping) def test_text_skip(self): summary = self.runner.run(self.testcase_cli_path) self.assertEqual(summary["stat"]["teststeps"]["skipped"], 4) def test_save_variables_output(self): testcases = [ { "config": { 'name': "post data", 'variables': { "var1": "abc", "var2": "def" }, "export": ["status_code", "req_data"] }, "teststeps": [ { "name": "post data", "request": { "url": "{}/post".format(HTTPBIN_SERVER), "method": "POST", "headers": { "User-Agent": "python-requests/2.18.4", "Content-Type": "application/json" }, "data": "$var1" }, "extract": { "status_code": "status_code", "req_data": "content.data" }, "validate": [ {"eq": ["status_code", 200]} ] } ] } ] tests_mapping = { "testcases": testcases } self.runner.run_tests(tests_mapping) vars_out = self.runner.get_vars_out() self.assertIsInstance(vars_out, list) self.assertEqual(vars_out[0]["in"]["var1"], "abc") self.assertEqual(vars_out[0]["in"]["var2"], "def") self.assertEqual(vars_out[0]["out"]["status_code"], 200) self.assertEqual(vars_out[0]["out"]["req_data"], "abc") def test_save_variables_output_with_parameters(self): testcase_file_path = os.path.join( os.getcwd(), 'tests/testsuites/create_users_with_parameters.yml') self.runner.run(testcase_file_path) vars_out = self.runner.get_vars_out() self.assertIsInstance(vars_out, list) self.assertEqual(len(vars_out), 6) self.assertEqual(vars_out[0]["in"]["uid"], 101) self.assertEqual(vars_out[0]["in"]["device_sn"], "TESTSUITE_X1") token1 = vars_out[0]["out"]["session_token"] self.assertEqual(len(token1), 16) self.assertEqual(vars_out[5]["in"]["uid"], 103) self.assertEqual(vars_out[5]["in"]["device_sn"], "TESTSUITE_X2") token2 = vars_out[0]["out"]["session_token"] self.assertEqual(len(token2), 16) self.assertEqual(token1, token2) def test_html_report(self): runner = HttpRunner(failfast=True) summary = runner.run(self.testcase_cli_path) self.assertEqual(summary["stat"]["testcases"]["total"], 1) self.assertEqual(summary["stat"]["teststeps"]["total"], 10) self.assertEqual(summary["stat"]["teststeps"]["skipped"], 4) report_save_dir = os.path.join(os.getcwd(), 'reports', "demo") report.gen_html_report(summary, report_dir=report_save_dir) self.assertGreater(len(os.listdir(report_save_dir)), 0) shutil.rmtree(report_save_dir) def test_html_report_with_fixed_report_file(self): runner = HttpRunner(failfast=True) summary = runner.run(self.testcase_cli_path) self.assertEqual(summary["stat"]["testcases"]["total"], 1) self.assertEqual(summary["stat"]["teststeps"]["total"], 10) self.assertEqual(summary["stat"]["teststeps"]["skipped"], 4) report_file = os.path.join(os.getcwd(), 'reports', "demo", "test.html") report.gen_html_report(summary, report_file=report_file) report_save_dir = os.path.dirname(report_file) self.assertEqual(len(os.listdir(report_save_dir)), 1) self.assertTrue(os.path.isfile(report_file)) shutil.rmtree(report_save_dir) def test_log_file(self): log_file_path = os.path.join(os.getcwd(), 'reports', "test_log_file.log") runner = HttpRunner(failfast=True, log_file=log_file_path) runner.run(self.testcase_cli_path) self.assertTrue(os.path.isfile(log_file_path)) os.remove(log_file_path) def test_run_testcases(self): summary = self.runner.run_tests(self.tests_mapping) self.assertTrue(summary["success"]) self.assertEqual(summary["stat"]["testcases"]["total"], 1) self.assertEqual(summary["stat"]["teststeps"]["total"], 2) self.assertIn("details", summary) self.assertIn("records", summary["details"][0]) def test_run_yaml_upload(self): upload_cases_list = [ "tests/httpbin/upload.yml", "tests/httpbin/upload.v2.yml" ] for upload_case in upload_cases_list: summary = self.runner.run(upload_case) self.assertTrue(summary["success"]) self.assertEqual(summary["stat"]["testcases"]["total"], 1) self.assertEqual(summary["stat"]["teststeps"]["total"], 2) self.assertIn("details", summary) self.assertIn("records", summary["details"][0]) def test_run_post_data(self): testcases = [ { "config": { 'name': "post data", 'variables': [] }, "teststeps": [ { "name": "post data", "request": { "url": "{}/post".format(HTTPBIN_SERVER), "method": "POST", "headers": { "User-Agent": "python-requests/2.18.4", "Content-Type": "application/json" }, "data": "abc" }, "validate": [ {"eq": ["status_code", 200]} ] } ] } ] tests_mapping = { "testcases": testcases } summary = self.runner.run_tests(tests_mapping) self.assertTrue(summary["success"]) self.assertEqual(summary["stat"]["testcases"]["total"], 1) self.assertEqual(summary["stat"]["teststeps"]["total"], 1) resp_json = json.loads(summary["details"][0]["records"][0]["meta_datas"]["data"][0]["response"]["body"]) self.assertEqual( resp_json["data"], "abc" ) def test_html_report_repsonse_image(self): runner = HttpRunner(failfast=True) summary = runner.run("tests/httpbin/load_image.yml") report_save_dir = os.path.join(os.getcwd(), 'reports', "demo") report_path = report.gen_html_report(summary, report_dir=report_save_dir) self.assertTrue(os.path.isfile(report_path)) shutil.rmtree(report_save_dir) def test_testcase_layer_with_api(self): summary = self.runner.run("tests/testcases/setup.yml") self.assertTrue(summary["success"]) self.assertEqual(summary["details"][0]["records"][0]["name"], "get token (setup)") self.assertEqual(summary["stat"]["testcases"]["total"], 1) self.assertEqual(summary["stat"]["teststeps"]["total"], 2) def test_testcase_layer_with_testcase(self): summary = self.runner.run("tests/testsuites/create_users.yml") self.assertTrue(summary["success"]) self.assertEqual(summary["stat"]["testcases"]["total"], 2) self.assertEqual(summary["stat"]["teststeps"]["total"], 4) def test_validate_script(self): summary = self.runner.run("tests/httpbin/validate.yml") self.assertFalse(summary["success"]) def test_run_httprunner_with_hooks(self): testcase_file_path = os.path.join( os.getcwd(), 'tests/httpbin/hooks.yml') start_time = time.time() summary = self.runner.run(testcase_file_path) end_time = time.time() self.assertTrue(summary["success"]) self.assertLess(end_time - start_time, 60) def test_run_httprunner_with_teardown_hooks_alter_response(self): testcases = [ { "config": {"name": "test teardown hooks"}, "teststeps": [ { "name": "test teardown hooks", "request": { "url": "{}/headers".format(HTTPBIN_SERVER), "method": "GET", "data": "abc" }, "teardown_hooks": [ "${alter_response($response)}" ], "validate": [ {"eq": ["status_code", 500]}, {"eq": ["headers.content-type", "html/text"]}, {"eq": ["json.headers.Host", "127.0.0.1:8888"]}, {"eq": ["content.headers.Host", "127.0.0.1:8888"]}, {"eq": ["text.headers.Host", "127.0.0.1:8888"]}, {"eq": ["new_attribute", "new_attribute_value"]}, {"eq": ["new_attribute_dict", {"key": 123}]}, {"eq": ["new_attribute_dict.key", 123]} ] } ] } ] tests_mapping = { "project_mapping": loader.load_project_data("tests"), "testcases": testcases } summary = self.runner.run_tests(tests_mapping) self.assertTrue(summary["success"]) def test_run_httprunner_with_teardown_hooks_not_exist_attribute(self): testcases = [ { "config": { "name": "test teardown hooks" }, "teststeps": [ { "name": "test teardown hooks", "request": { "url": "{}/headers".format(HTTPBIN_SERVER), "method": "GET", "data": "abc" }, "teardown_hooks": [ "${alter_response($response)}" ], "validate": [ {"eq": ["attribute_not_exist", "new_attribute"]} ] } ] } ] tests_mapping = { "project_mapping": loader.load_project_data("tests"), "testcases": testcases } summary = self.runner.run_tests(tests_mapping) self.assertFalse(summary["success"]) self.assertEqual(summary["stat"]["teststeps"]["errors"], 1) def test_run_httprunner_with_teardown_hooks_error(self): testcases = [ { "config": { "name": "test teardown hooks" }, "teststeps": [ { "name": "test teardown hooks", "request": { "url": "{}/headers".format(HTTPBIN_SERVER), "method": "GET", "data": "abc" }, "teardown_hooks": [ "${alter_response_error($response)}" ] } ] } ] tests_mapping = { "project_mapping": loader.load_project_data("tests"), "testcases": testcases } summary = self.runner.run_tests(tests_mapping) self.assertFalse(summary["success"]) self.assertEqual(summary["stat"]["teststeps"]["errors"], 1) def test_run_api(self): path = "tests/httpbin/api/get_headers.yml" summary = self.runner.run(path) self.assertTrue(summary["success"]) self.assertEqual(summary["stat"]["testcases"]["total"], 1) self.assertEqual(summary["stat"]["teststeps"]["total"], 1) self.assertEqual(summary["stat"]["teststeps"]["successes"], 1) def test_request_302_logs(self): path = "tests/httpbin/api/302_redirect.yml" summary = self.runner.run(path) self.assertTrue(summary["success"]) self.assertEqual(summary["stat"]["testcases"]["total"], 1) self.assertEqual(summary["stat"]["teststeps"]["total"], 1) self.assertEqual(summary["stat"]["teststeps"]["successes"], 1) req_resp_data = summary["details"][0]["records"][0]["meta_datas"]["data"] self.assertEqual(len(req_resp_data), 2) self.assertEqual(req_resp_data[0]["response"]["status_code"], 302) self.assertEqual(req_resp_data[1]["response"]["status_code"], 200) def test_request_302_logs_teardown_hook(self): path = "tests/httpbin/api/302_redirect_teardown_hook.yml" summary = self.runner.run(path) self.assertTrue(summary["success"]) self.assertEqual(summary["stat"]["testcases"]["total"], 1) self.assertEqual(summary["stat"]["teststeps"]["total"], 1) self.assertEqual(summary["stat"]["teststeps"]["successes"], 1) req_resp_data = summary["details"][0]["records"][0]["meta_datas"]["data"] self.assertEqual(len(req_resp_data), 2) self.assertEqual(req_resp_data[0]["response"]["status_code"], 302) self.assertEqual(req_resp_data[1]["response"]["status_code"], 500) def test_request_with_params(self): path = "tests/httpbin/api/302_redirect.yml" summary = self.runner.run(path) self.assertTrue(summary["success"]) self.assertEqual(summary["stat"]["testcases"]["total"], 1) self.assertEqual(summary["stat"]["teststeps"]["total"], 1) self.assertEqual(summary["stat"]["teststeps"]["successes"], 1) req_resp_data = summary["details"][0]["records"][0]["meta_datas"]["data"] self.assertEqual(len(req_resp_data), 2) self.assertIn( "url=https%3A%2F%2Fgithub.com", req_resp_data[0]["request"]["url"] ) def test_run_api_folder(self): api_folder = "tests/httpbin/api/" summary = self.runner.run(api_folder) print(summary["stat"]["testcases"]["total"]) print(len(summary["details"])) self.assertTrue(summary["success"]) self.assertEqual(summary["stat"]["testcases"]["total"], 3) self.assertEqual(summary["stat"]["teststeps"]["total"], 3) self.assertEqual(summary["stat"]["teststeps"]["successes"], 3) self.assertEqual(len(summary["details"]), 3) self.assertEqual(summary["details"][0]["stat"]["total"], 1) self.assertEqual(summary["details"][1]["stat"]["total"], 1) self.assertEqual(summary["details"][2]["stat"]["total"], 1) def test_run_testcase_hardcode(self): for testcase_file_path in self.testcase_file_path_list: summary = self.runner.run(testcase_file_path) self.assertTrue(summary["success"]) self.assertEqual(summary["stat"]["testcases"]["total"], 1) self.assertEqual(summary["stat"]["teststeps"]["total"], 3) self.assertEqual(summary["stat"]["teststeps"]["successes"], 3) def test_run_testcase_template_variables(self): testcase_file_path = os.path.join( os.getcwd(), 'tests/data/demo_testcase_variables.yml') summary = self.runner.run(testcase_file_path) self.assertTrue(summary["success"]) def test_run_testcase_template_import_functions(self): testcase_file_path = os.path.join( os.getcwd(), 'tests/data/demo_testcase_functions.yml') summary = self.runner.run(testcase_file_path) self.assertTrue(summary["success"]) def test_run_testcase_layered(self): testcase_file_path = os.path.join( os.getcwd(), 'tests/data/demo_testcase_layer.yml') summary = self.runner.run(testcase_file_path) self.assertTrue(summary["success"]) self.assertEqual(len(summary["details"]), 1) def test_run_testcase_output(self): testcase_file_path = os.path.join( os.getcwd(), 'tests/data/demo_testcase_layer.yml') summary = self.runner.run(testcase_file_path) self.assertTrue(summary["success"]) self.assertIn("token", summary["details"][0]["in_out"]["out"]) # TODO: add # self.assertIn("user_agent", summary["details"][0]["in_out"]["in"]) def test_run_testcase_with_variables_mapping(self): testcase_file_path = os.path.join( os.getcwd(), 'tests/data/demo_testcase_layer.yml') variables_mapping = { "app_version": '2.9.7' } summary = self.runner.run(testcase_file_path, mapping=variables_mapping) self.assertTrue(summary["success"]) self.assertIn("token", summary["details"][0]["in_out"]["out"]) # TODO: add # self.assertGreater(len(summary["details"][0]["in_out"]["in"]), 3) def test_run_testcase_with_parameters(self): testcase_file_path = os.path.join( os.getcwd(), 'tests/testsuites/create_users_with_parameters.yml') summary = self.runner.run(testcase_file_path) self.assertTrue(summary["success"]) self.assertEqual(len(summary["details"]), 3 * 2) self.assertEqual(summary["stat"]["testcases"]["total"], 6) self.assertEqual(summary["stat"]["teststeps"]["total"], 3 * 2 * 2) self.assertEqual( summary["details"][0]["name"], "create user 101 and check result for TESTSUITE_X1." ) self.assertEqual( summary["details"][5]["name"], "create user 103 and check result for TESTSUITE_X2." ) self.assertEqual( summary["details"][0]["stat"]["total"], 2 ) records_name_list = [ summary["details"][i]["records"][1]["meta_datas"][1]["name"] for i in range(6) ] self.assertEqual( set(records_name_list), { "create user 101 for TESTSUITE_X1", "create user 101 for TESTSUITE_X2", "create user 102 for TESTSUITE_X1", "create user 102 for TESTSUITE_X2", "create user 103 for TESTSUITE_X1", "create user 103 for TESTSUITE_X2" } ) def test_validate_response_content(self): testcase_file_path = os.path.join( os.getcwd(), 'tests/httpbin/basic.yml') summary = self.runner.run(testcase_file_path) self.assertTrue(summary["success"]) def test_html_report_xss(self): testcases = [ { "config": { 'name': "post data" }, "teststeps": [ { "name": "post data", "request": { "url": "{}/anything".format(HTTPBIN_SERVER), "method": "POST", "headers": { "Content-Type": "application/json" }, "json": { 'success': False, "person": "<img src=x onerror=alert(1)>" } }, "validate": [ {"eq": ["status_code", 200]} ] } ] } ] tests_mapping = { "testcases": testcases } summary = self.runner.run(tests_mapping) report_path = report.gen_html_report(summary) with open(report_path) as f: content = f.read() m = re.findall( re.escape(""person": "<img src=x onerror=alert(1)>""), content ) self.assertEqual(len(m), 2)