Пример #1
0
    def pull(self, project_id, branch, root_path):

        project = self.get_project_id(project_id)
        info = project.repository_tree(all=True, recursive=True, as_list=True)
        file_list = []
        if not os.path.isdir(root_path):
            os.makedirs(root_path)
        os.chdir(root_path)
        # 调用创建目录的函数并生成文件名列表
        for info_dir in range(len(info)):
            if info[info_dir]['type'] == 'tree':
                dir_name = info[info_dir]['path']
                self.create_dir(dir_name)
            else:
                file_name = info[info_dir]['path']
                file_list.append(file_name)
        for info_file in range(len(file_list)):
            # 开始下载
            getf = project.files.get(file_path=file_list[info_file],
                                     ref=branch)
            content = getf.decode()
            with open(file_list[info_file], 'wb') as code:
                logger.info("\033[0;32;40m开始下载文件: \033[0m{0}".format(
                    file_list[info_file]))
                code.write(content)
Пример #2
0
 def create(self, request, *args, **kwargs):
     serializer = self.get_serializer(data=request.data)
     serializer.is_valid(raise_exception=True)
     self.perform_create(serializer)
     if request.data.get('timer_enable') and request.data.get('crontab'):
         crontab = request.data.get('crontab').replace('?', '*')
         crontab = crontab.split(' ')
         if len(crontab) == 7:
             # 包含秒 包含年
             crontab = crontab[1:-1]
         elif len(crontab) == 6:
             # 包含秒 不包含年
             crontab = crontab[1:]
         crontab_kwargs = {
             'minute': crontab[0],
             'hour': crontab[1],
             'day_of_week': crontab[4],
             'day_of_month': crontab[2],
             'month_of_year': crontab[3]
         }
         with transaction.atomic():
             save_id = transaction.savepoint()
             try:
                 schedule, _ = CrontabSchedule.objects.get_or_create(
                     minute=crontab_kwargs.get('minute', '*'),
                     hour=crontab_kwargs.get('hour', '*'),
                     day_of_week=crontab_kwargs.get('day_of_week', '*'),
                     day_of_month=crontab_kwargs.get('day_of_month', '*'),
                     month_of_year=crontab_kwargs.get('month_of_year', '*'),
                     timezone=pytz.timezone(TIME_ZONE))
                 dt = datetime.now().strftime('%Y%m%d%H%M%S')
                 _periodic_task = PeriodicTask.objects.create(
                     name=dt + '-' + 'case测试计划定时任务' + '-' +
                     serializer.data.get('plan_id'),
                     task='case_test_task_timing_executor',
                     args=json.dumps([
                         serializer.data.get('project_id'),
                         serializer.data.get('plan_id')
                     ]),
                     enabled=True,
                     crontab=schedule)
                 logger.info(
                     "timing case testplan:{} create success!".format(
                         serializer.data.get('plan_id')))
             except Exception as e:
                 transaction.savepoint_rollback(save_id)
                 logger.error(
                     'timing case testplan:{} create failed!,error:{}'.
                     format(serializer.data.get('plan_id'), e))
     headers = self.get_success_headers(serializer.data)
     return Response(serializer.data,
                     status=status.HTTP_201_CREATED,
                     headers=headers)
Пример #3
0
    def executor(cls, case_job, project_id, test_plan_uid, task_id):
        """
        执行器
        :param case_job:
        :param project_id:
        :param test_plan_uid:
        :param task_id:
        :return:
        """
        default_venv = ConfigParser.get_config('python_venv', 'venv_path')
        case_job.state = CaseJobState.RUNNING
        case_job.save()

        case_path = case_job.case_path
        case_dir = '/'.join(case_path.split('/')[0:3])
        case_venv = os.path.join(settings.BASE_DIR, 'case_house', case_dir, 'venv')
        cmd_path = os.path.join(settings.BASE_DIR, 'case_house', case_dir)
        if os.path.exists(case_venv):
            venv_path = case_venv
        else:
            venv_path = default_venv
        file_path, file_name = os.path.split(case_path)

        report_name = case_path.split('/')[-1].split('.')[0] + '.html'
        result_log_name = case_path.split('/')[-1].split('.')[0] + '.log'
        xml_name = case_path.split('/')[-1].split('.')[0] + '.xml'

        report_path = os.path.join(MEDIA_ROOT, 'html-report', str(project_id), test_plan_uid, str(task_id))
        try:
            if not os.path.exists(report_path):
                os.makedirs(report_path)
        except FileExistsError:
            pass

        if 'test' in os.path.splitext(file_name)[0] and os.path.splitext(file_name)[1].startswith('.py'):
            # 是pytest 脚本
            try:
                cmd = '{} {} -vv -s --html={} --self-contained-html --result-log={} --junit-xml={}'.format(
                    os.path.join(venv_path, 'bin/pytest'),
                    os.path.join(settings.BASE_DIR, 'case_house', case_path),
                    os.path.join(report_path, report_name),
                    os.path.join(report_path, result_log_name),
                    os.path.join(report_path, xml_name))
                logger.info(cmd)
                p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, cwd=cmd_path)
                out = p.stdout
                read_data = out.read().decode("utf-8", "ignore")
                case_job.log = read_data
                case_job.report_path = '/media/html-report/{}/{}/{}/{}'.format(project_id, test_plan_uid, task_id,
                                                                               report_name)
                case_result = read_data.split('\n')[-2]
                case_job.result = case_result.replace('=', '').strip(' ')
                case_job.state = CaseJobState.FINISH
                case_job.save()
                return True
            except Exception as es:
                logger.error("case job excepted:{}".format(es))
                case_job.state = CaseJobState.FAILED
                case_job.save()
                return False
        elif os.path.splitext(file_name)[1] == '.py':
            # 普通python脚本
            try:
                p = subprocess.Popen(
                    '{} {}'.format(
                        os.path.join(venv_path, 'bin/python'),
                        os.path.join(settings.BASE_DIR, 'case_house', case_path)), shell=True, stdout=subprocess.PIPE,
                    cwd=cmd_path)
                out = p.stdout
                read_data = out.read().decode("utf-8", "ignore")
                case_job.log = read_data
                case_job.state = CaseJobState.FINISH
                case_job.save()
                return True
            except Exception as es:
                logger.error("case job excepted:{}".format(es))
                case_job.state = CaseJobState.FAILED
                case_job.save()
                return False
        elif os.path.splitext(file_name)[1] == '.yml':
            # HttpRunner脚本
            try:
                case_task_id = case_job.case_task_id
                test_plan_uid = CaseTestPlanTaskModel.objects.get(id=case_task_id).test_plan_uid
                env_file = CaseTestPlanModel.objects.get(plan_id=test_plan_uid).env_file
                if env_file:
                    p = subprocess.Popen(
                        '{} {} --dot-env-path {} --report-file {}'.format(
                            os.path.join(venv_path, 'bin/hrun'),
                            os.path.join(settings.BASE_DIR, 'case_house', case_path),
                            os.path.join(settings.BASE_DIR, 'case_house', env_file),
                            os.path.join(report_path, report_name)),
                        shell=True, stdout=subprocess.PIPE, cwd=cmd_path)
                else:
                    p = subprocess.Popen('{} {} --report-file {}'.format(
                        os.path.join(venv_path, 'bin/hrun'),
                        os.path.join(settings.BASE_DIR, 'case_house', case_path),
                        os.path.join(report_path, report_name)),
                        shell=True, stdout=subprocess.PIPE, cwd=cmd_path)
                out = p.stdout
                read_data = out.read().decode("utf-8", "ignore")
                case_job.report_path = '/media/html-report/{}/{}/{}/{}'.format(project_id, test_plan_uid, task_id,
                                                                               report_name)
                case_job.log = read_data
                # case_job.result = case_result.replace('=', '').strip(' ')
                case_job.state = CaseJobState.FINISH
                case_job.save()
                return True
            except Exception as es:
                logger.error("case job excepted:{}".format(es))
                case_job.state = CaseJobState.FAILED
                case_job.save()
                return False
Пример #4
0
    def dispose_response(self, interface, response):
        """
        请求处理器
        """
        # 处理断言
        for _assert in interface.asserts:
            if _assert['assertType'] == "regular":
                # 正则判断逻辑
                if not isRegular(_assert['expressions']):
                    logger.error(
                        'interface Id:{}, testPlan Id:{} expressions:{} is not regular'.format(interface.id,
                                                                                               self.test_plan_id,
                                                                                               _assert['expressions']))
                    update_api_job_fail(self.test_plan_id, interface.id, response)
                    break
                else:
                    pattern = isRegular(_assert['expressions'])
                    re_result = assert_regular(pattern, response.text)
                    logger.info("正则匹配结果:{}".format(re_result))
                    if not re_result:  # 断言失败
                        update_api_job_fail(self.test_plan_id, interface.id, response)  # 跟新interfaceJob状态失败
                        break
                    else:
                        try:
                            calculate_fun = getattr(operation, _assert['calculate'])
                        except AttributeError as es:
                            logger.error("calculate rule {} is not exist!".format(_assert['calculate']))
                            update_api_job_fail(self.test_plan_id, interface.id, response)
                            break
                        if not calculate_fun(re_result, _assert['expect']):
                            update_api_job_fail(self.test_plan_id, interface.id, response)  # 跟新interfaceJob状态失败
                            break
            elif _assert['assertType'] == "delimiter":
                # 分隔符取值
                delimiter_result = assert_delimiter(_assert['expressions'], response)
                logger.info("分隔符匹配结果: {}".format(delimiter_result))
                if delimiter_result == 'EXCEPTION':
                    logger.error(
                        "delimiter error:{}, interfaceJobId: {}, test_plan Id:{}".format(_assert['expressions'],
                                                                                         interface.id,
                                                                                         self.test_plan_id))
                    update_api_job_fail(self.test_plan_id, interface.id, response)
                    break
                elif delimiter_result == dict():
                    update_api_job_fail(self.test_plan_id, interface.id, response)
                    break
                else:
                    try:
                        calculate_fun = getattr(operation, _assert['calculate'])
                    except AttributeError as es:
                        logger.error("calculate rule {} is not exist!".format(_assert['calculate']))
                        update_api_job_fail(self.test_plan_id, interface.id, response)
                        break
                    if not calculate_fun(delimiter_result, _assert['expect']):
                        update_api_job_fail(self.test_plan_id, interface.id, response)
                        break
        else:  # 所有断言验证通过
            update_api_job_success(self.test_plan_id, interface.id, response)

        # 处理提取规则
        extracts_result = {}  # 提取结果的集合
        for extract in interface.extract:
            if extract['extractType'] == "regular":
                if not isRegular(extract['expressions']):
                    logger.error(
                        'interface Id:{}, testPlan Id:{} expressions:{} is not regular'.format(interface.id,
                                                                                               self.test_plan_id,
                                                                                               extract['expressions']))
                pattern = isRegular(extract['expressions'])
                re_result = assert_regular(pattern, response.text)
                if not re_result:  # 没有匹配到结果
                    extracts_result[extract['variable_name']] = ''
                else:
                    extracts_result[extract['variable_name']] = re_result

            elif extract['extractType'] == "delimiter":
                delimiter_result = assert_delimiter(extract['expressions'], response)
                if delimiter_result == 'EXCEPTION':
                    logger.error(
                        "delimiter error:{}, interfaceJobId: {}, test_plan Id:{}".format(extract['expressions'],
                                                                                         interface.id,
                                                                                         self.test_plan_id))
                    extracts_result[extract['variable_name']] = ''
                else:
                    extracts_result[extract['variable_name']] = delimiter_result
        return extracts_result
Пример #5
0
def branch_pull(gitlab_info, project_id, branch_name):
    """
    录取gitlab指定分支代码
    """
    instance = GitlabAPI(gitlab_url=gitlab_info.get('gitlab_url'),
                         private_token=gitlab_info.get('private_token'))
    project = instance.gl.projects.get(project_id)
    obj_tuple = GitCaseModel.objects.update_or_create(
        gitlab_url=gitlab_info.get('gitlab_url'),
        gitlab_project_name=project.name,
        gitlab_project_id=project.id,
        branch_name=branch_name)
    obj_tuple[0].status = BranchState.PULLING
    obj_tuple[0].save()
    cache_key = "private_token:" + gitlab_info.get(
        'private_token') + "-" + "project_id:" + str(
            project_id) + "-" + "branch_name:" + branch_name
    cache.set(cache_key, BranchState.PULLING)
    try:
        info = project.repository_tree(ref=branch_name,
                                       all=True,
                                       recursive=True,
                                       as_list=True)
        file_list = []
        root_path = os.path.join(
            BASE_DIR, 'case_house',
            gitlab_info.get('gitlab_url').replace(':', '-').replace(
                '.', '-').replace('/', ''), branch_name, project.name)
        if not os.path.isdir(root_path):
            os.makedirs(root_path)
        os.chdir(root_path)
        # 调用创建目录的函数并生成文件名列表
        for info_dir in range(len(info)):
            if info[info_dir]['type'] == 'tree':
                dir_name = info[info_dir]['path']
                create_dir(dir_name)
            else:
                file_name = info[info_dir]['path']
                file_list.append(file_name)
        file_list_len = len(file_list)
        for index, info_file in enumerate(range(file_list_len)):
            # 开始下载
            getf = project.files.get(file_path=file_list[info_file],
                                     ref=branch_name)
            content = getf.decode()
            with open(file_list[info_file], 'wb') as code:
                logger.info("\033[0;32;40m开始下载文件: \033[0m{0}".format(
                    file_list[info_file]))
                code.write(content)
            finish_progress = float('%.2f' %
                                    ((index + 1) / file_list_len)) * 100
            cache.set(cache_key + "progress", finish_progress, 3)
        branch_obj = GitCaseModel.objects.get(
            gitlab_url=gitlab_info.get('gitlab_url'),
            gitlab_project_id=project.id,
            gitlab_project_name=project.name,
            branch_name=branch_name,
        )
        branch_obj.status = BranchState.DONE
        branch_obj.save()
        cache.set(cache_key, BranchState.DONE)
        return True
    except Exception as es:
        logger.error(str(es))
        branch_obj = GitCaseModel.objects.get(
            gitlab_url=gitlab_info.get('gitlab_url'),
            gitlab_project_id=project.id,
            gitlab_project_name=project.name,
            branch_name=branch_name,
        )
        branch_obj.status = BranchState.FAILED
        branch_obj.save()
        cache.set(cache_key, BranchState.FAILED)
        return False
Пример #6
0
def create_dir(dir_name):
    if not os.path.isdir(dir_name):
        logger.info("\033[0;32;40m开始创建目录: \033[0m{0}".format(dir_name))
        os.makedirs(dir_name)
        time.sleep(0.1)