class TreeView(APIView): """ 树形结构操作 """ # authentication_classes = [OnlyGetAuthenticator, ] @method_decorator(request_log(level='INFO')) def get(self, request, **kwargs): """ 返回树形结构 当前最带节点ID """ try: tree_type = request.query_params['type'] tree = models.Relation.objects.get(project__id=kwargs['pk'], type=tree_type) except KeyError: return Response(response.KEY_MISS) except ObjectDoesNotExist: return Response(response.SYSTEM_ERROR) body = eval(tree.tree) # list tree = { "tree": body, "id": tree.id, "success": True, "max": get_tree_max_id(body) } return Response(tree) @method_decorator(request_log(level='INFO')) def patch(self, request, **kwargs): """ 修改树形结构,ID不能重复 """ try: body = request.data['body'] mode = request.data['mode'] relation = models.Relation.objects.get(id=kwargs['pk']) relation.tree = body relation.save() except KeyError: return Response(response.KEY_MISS) except ObjectDoesNotExist: return Response(response.SYSTEM_ERROR) # mode -> True remove node if mode: prepare.tree_end(request.data, relation.project) response.TREE_UPDATE_SUCCESS['tree'] = body response.TREE_UPDATE_SUCCESS['max'] = get_tree_max_id(body) return Response(response.TREE_UPDATE_SUCCESS)
class HostIPView(viewsets.ModelViewSet): """ 域名管理视图 create: 传id时认为是在复制,不传时在新建 """ pagination_class = pagination.MyPageNumberPagination permission_classes = (DjangoModelPermissions, IsBelongToProject) def get_queryset(self): return models.HostIP.objects.filter( project__id=self.request.query_params['project']).order_by( '-update_time') def get_serializer_class(self): if self.action in ['create', 'update', 'partial_update']: return serializers.HostIPSerializerPost else: return serializers.HostIPSerializerList @method_decorator(request_log(level='INFO')) def create(self, request, *args, **kwargs): if 'id' in request.data.keys(): pk = request.data['id'] name = request.data['name'] host_info = self.get_queryset().get(id=pk) # models.HostIP.objects.get(id=pk) request_data = { "name": name, "hostInfo": json.loads(host_info.hostInfo), "project": host_info.project_id, "base_url": host_info.base_url } else: request_data = request.data serializer = self.get_serializer(data=request_data) serializer.is_valid(raise_exception=True) self.perform_create(serializer) headers = self.get_success_headers(serializer.data) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) @method_decorator(request_log(level='INFO')) def destroy(self, request, *args, **kwargs): if kwargs.get('pk') and int(kwargs['pk']) != -1: instance = self.get_object() self.perform_destroy(instance) elif request.data: for content in request.data: self.kwargs['pk'] = content['id'] instance = self.get_object() self.perform_destroy(instance) return Response(status=status.HTTP_204_NO_CONTENT)
class DebugTalkView(GenericViewSet): """ DebugTalk update """ # authentication_classes = [OnlyGetAuthenticator, ] serializer_class = serializers.DebugTalkSerializer @method_decorator(request_log(level='INFO')) def debugtalk(self, request, **kwargs): """ 得到debugtalk code """ pk = kwargs.pop('pk') try: queryset = models.Debugtalk.objects.get(project__id=pk) except ObjectDoesNotExist: return Response(response.DEBUGTALK_NOT_EXISTS) serializer = self.get_serializer(queryset, many=False) return Response(serializer.data) @method_decorator(request_log(level='INFO')) def update(self, request): """ 编辑debugtalk.py 代码并保存 """ pk = request.data['id'] try: models.Debugtalk.objects.filter(id=pk). \ update(code=request.data['code'], updater=request.user.username) except ObjectDoesNotExist: return Response(response.SYSTEM_ERROR) return Response(response.DEBUGTALK_UPDATE_SUCCESS) @method_decorator(request_log(level='INFO')) def run(self, request): try: code = request.data["code"] except KeyError: return Response(response.KEY_MISS) debug = DebugCode(code) debug.run() resp = { "msg": debug.resp, "success": True, "code": "0001" } return Response(resp)
class PycodeView(ModelViewSet): """ 驱动代码模块 """ serializer_class = serializers.PycodeSerializer pagination_class = pagination.MyPageNumberPagination permission_classes = (DjangoModelPermissions, IsBelongToProject) def get_queryset(self): project = self.request.query_params["project"] queryset = models.Pycode.objects.filter( project_id=project).order_by('-update_time') if self.action == 'list': queryset = queryset.filter( name__contains=self.request.query_params["search"]) return queryset @method_decorator(request_log(level='INFO')) def destroy(self, request, *args, **kwargs): if kwargs.get('pk') and int(kwargs['pk']) != -1: instance = self.get_object() if instance.name == 'debugtalk.py': Response(status=status.HTTP_423_LOCKED) else: self.perform_destroy(instance) elif request.data: for content in request.data: self.kwargs['pk'] = content['id'] instance = self.get_object() if instance.name != 'debugtalk.py': self.perform_destroy(instance) return Response(status=status.HTTP_204_NO_CONTENT)
class DashboardView(GenericViewSet): """ dashboard信息 """ # permission_classes = (DjangoModelPermissions, IsBelongToProject) @method_decorator(request_log(level='INFO')) def get(self, request, **kwargs): return Response(prepare.get_project_detail(kwargs['pk']))
class DashboardView(GenericViewSet): """ dashboard信息 """ @method_decorator(request_log(level='INFO')) def get(self, request, **kwargs): return Response(prepare.get_project_detail(kwargs['pk']))
class DownloadView(APIView): """下载文件接口 """ @method_decorator(request_log(level='DEBUG')) def post(self, request, **kwargs): """下载文件 请求参数:{ fileType: int (1:testdata, 2: report_excel 3: report_html) id: int, project: int } """ try: file_type = int(request.data["fileType"]) idno = int(request.data["id"]) project = int(request.data["project"]) except KeyError: return Response(response.KEY_MISS, status=status.HTTP_400_BAD_REQUEST) try: if file_type == 1: fileObject = models.ModelWithFileField.objects.get( project_id=project, id=idno) filename = fileObject.name filepath = os.path.join(MEDIA_ROOT, str(fileObject.file)) else: fileObject = models.ReportDetail.objects.get( project_id=project, report_id=idno) filename = fileObject.name summary = json.loads(fileObject.summary) filepath = write_excel_log(summary) fileresponse = FileResponse(open(filepath, 'rb')) fileresponse["Content-Type"] = "application/octet-stream" fileresponse[ "Content-Disposition"] = "attachment;filename={}".format( filename) return fileresponse except ObjectDoesNotExist: return Response(response.FILE_DOWNLOAD_FAIL, status=status.HTTP_400_BAD_REQUEST)
class ProjectView(ModelViewSet): """ 项目增删改查 """ queryset = models.Project.objects.all().order_by('-update_time') serializer_class = serializers.ProjectSerializer pagination_class = pagination.MyCursorPagination permission_classes = (DjangoModelPermissions,) @method_decorator(request_log(level='INFO')) def single(self, request, **kwargs): """ 得到单个项目相关统计信息 """ pk = kwargs.pop('pk') try: queryset = models.Project.objects.get(id=pk) except ObjectDoesNotExist: return Response(response.PROJECT_NOT_EXISTS) serializer = self.get_serializer(queryset, many=False) project_info = prepare.get_project_detail(pk) project_info.update(serializer.data) return Response(project_info) def perform_create(self, serializer): instance = serializer.save() # 生成debugtalk.py文件 models.Pycode.objects.create(project=instance, name="debugtalk.py", desc="项目的根目录文件,项目中所使用函数都从此中调用") # 自动生成API tree models.Relation.objects.create(project=instance) # 自动生成Test Tree models.Relation.objects.create(project=instance, type=2) def perform_destroy(self, instance): project_id = instance.id celery_models.PeriodicTask.objects.filter(description=project_id).delete() instance.delete()
class CaseStepView(APIView): """ 测试用例step操作视图 """ @method_decorator(request_log(level='INFO')) def get(self, request, **kwargs): """ 返回用例集信息 """ pk = kwargs['pk'] queryset = models.CaseStep.objects.filter(case__id=pk).order_by('step') serializer = serializers.CaseStepSerializer(instance=queryset, many=True) resp = { "case": serializers.CaseSerializer(instance=models.Case.objects.get(id=pk), many=False).data, "step": serializer.data } return Response(resp)
class PycodeRunView(GenericViewSet, mixins.RetrieveModelMixin): """ 驱动代码调试运行 """ serializer_class = serializers.PycodeSerializer def get_queryset(self): project = self.request.query_params["project"] queryset = models.Pycode.objects.filter( project_id=project).order_by('-update_time') return queryset @method_decorator(request_log(level='INFO')) def retrieve(self, request, *args, **kwargs): instance = self.get_object() serializer = self.get_serializer(instance) debug = DebugCode(serializer.data["code"], serializer.data["project"], serializer.data["name"]) debug.run() debug_rsp = {"msg": debug.resp} return Response(data=debug_rsp)
class VariablesView(GenericViewSet): serializer_class = serializers.VariablesSerializer queryset = models.Variables.objects permission_classes = (DjangoModelPermissions,) @method_decorator(request_log(level='DEBUG')) def list(self, request): project = request.query_params['project'] search = request.query_params["search"] queryset = self.get_queryset().filter(project__id=project).order_by('-update_time') if search != '': queryset = queryset.filter(key__contains=search) pagination_queryset = self.paginate_queryset(queryset) serializer = self.get_serializer(pagination_queryset, many=True) return self.get_paginated_response(serializer.data) @method_decorator(request_log(level='INFO')) def add(self, request): """ add new variables { key: str value: str project: int } """ try: project = models.Project.objects.get(id=request.data["project"]) except ObjectDoesNotExist: return Response(response.PROJECT_NOT_EXISTS) if models.Variables.objects.filter(key=request.data["key"], project=project).first(): return Response(response.VARIABLES_EXISTS) request.data["project"] = project models.Variables.objects.create(**request.data) return Response(response.CONFIG_ADD_SUCCESS) @method_decorator(request_log(level='INFO')) def update(self, request, **kwargs): """ pk: int { key: str value:str } """ pk = kwargs['pk'] try: variables = models.Variables.objects.get(id=pk) except ObjectDoesNotExist: return Response(response.VARIABLES_NOT_EXISTS) if models.Variables.objects.exclude(id=pk).filter(key=request.data['key']).first(): return Response(response.VARIABLES_EXISTS) variables.key = request.data["key"] variables.value = request.data["value"] variables.save() return Response(response.VARIABLES_UPDATE_SUCCESS) @method_decorator(request_log(level='INFO')) def delete(self, request, **kwargs): """ 删除一个变量 pk 删除多个 [{ id:int }] """ try: if kwargs.get('pk'): # 单个删除 models.Variables.objects.get(id=kwargs['pk']).delete() else: for content in request.data: models.Variables.objects.get(id=content['id']).delete() except ObjectDoesNotExist: return Response(response.VARIABLES_NOT_EXISTS) return Response(response.API_DEL_SUCCESS)
class ConfigView(GenericViewSet): serializer_class = serializers.ConfigSerializer queryset = models.Config.objects permission_classes = (DjangoModelPermissions,) @method_decorator(request_log(level='DEBUG')) def list(self, request): project = request.query_params['project'] search = request.query_params["search"] queryset = self.get_queryset().filter(project__id=project).order_by('-update_time') if search != '': queryset = queryset.filter(name__contains=search) pagination_queryset = self.paginate_queryset(queryset) serializer = self.get_serializer(pagination_queryset, many=True) return self.get_paginated_response(serializer.data) @method_decorator(request_log(level='DEBUG')) def all(self, request, **kwargs): """ get all config """ pk = kwargs["pk"] queryset = self.get_queryset().filter(project__id=pk). \ order_by('-update_time').values("id", "name") return Response(queryset) @method_decorator(request_log(level='INFO')) def add(self, request): """ add new config { name: str project: int body: dict } """ config = Format(request.data, level='config') config.parse() del config.testcase["skipIf"] try: config.project = models.Project.objects.get(id=config.project) except ObjectDoesNotExist: return Response(response.PROJECT_NOT_EXISTS) if models.Config.objects.filter(name=config.name, project=config.project).first(): return Response(response.CONFIG_EXISTS) config_body = { "name": config.name, "base_url": config.base_url, "body": config.testcase, "project": config.project } models.Config.objects.create(**config_body) return Response(response.CONFIG_ADD_SUCCESS) @method_decorator(request_log(level='INFO')) def update(self, request, **kwargs): """ pk: int { name: str, base_url: str, variables: [] parameters: [] request: [] } } """ pk = kwargs['pk'] try: config = models.Config.objects.get(id=pk) except ObjectDoesNotExist: return Response(response.CONFIG_NOT_EXISTS) format = Format(request.data, level="config") format.parse() del format.testcase["skipIf"] if models.Config.objects.exclude(id=pk).filter(name=format.name, project=config.project).first(): return Response(response.CONFIG_EXISTS) case_step = models.CaseStep.objects.filter(method="config", name=config.name) for case in case_step: case.name = format.name case.body = format.testcase case.save() config.name = format.name config.body = format.testcase config.base_url = format.base_url config.save() return Response(response.CONFIG_UPDATE_SUCCESS)
case_step = models.CaseStep.objects.filter(method="config", name=config.name) for case in case_step: case.name = format.name case.body = format.testcase case.save() config.name = format.name config.body = format.testcase config.base_url = format.base_url config.save() return Response(response.CONFIG_UPDATE_SUCCESS) @method_decorator(request_log(level='INFO')) def copy(self, request, **kwargs): """ pk: int { name: str } """ pk = kwargs['pk'] try: config = models.Config.objects.get(id=pk) except ObjectDoesNotExist: return Response(response.CONFIG_NOT_EXISTS) if models.Config.objects.filter(**request.data).first(): return Response(response.CONFIG_EXISTS)
class HostIPView(GenericViewSet): serializer_class = serializers.HostIPSerializer queryset = models.HostIP.objects @method_decorator(request_log(level='DEBUG')) def list(self, request): project = request.query_params['project'] queryset = self.get_queryset().filter( project__id=project).order_by('-update_time') pagination_queryset = self.paginate_queryset(queryset) serializer = self.get_serializer(pagination_queryset, many=True) return self.get_paginated_response(serializer.data) @method_decorator(request_log(level='INFO')) def add(self, request): """ add new variables { name: str value: str project: int } """ try: project = models.Project.objects.get(id=request.data["project"]) except ObjectDoesNotExist: return Response(response.PROJECT_NOT_EXISTS) if models.HostIP.objects.filter(name=request.data["name"], project=project).first(): return Response(response.HOSTIP_EXISTS) request.data["project"] = project models.HostIP.objects.create(**request.data) return Response(response.HOSTIP_ADD_SUCCESS) @method_decorator(request_log(level='INFO')) def update(self, request, **kwargs): """pk: int{ name: str value:str } """ pk = kwargs['pk'] try: host = models.HostIP.objects.get(id=pk) except ObjectDoesNotExist: return Response(response.HOSTIP_NOT_EXISTS) if models.HostIP.objects.exclude(id=pk).filter( name=request.data['name']).first(): return Response(response.HOSTIP_EXISTS) host.name = request.data["name"] host.value = request.data["value"] host.save() return Response(response.HOSTIP_UPDATE_SUCCESS) @method_decorator(request_log(level='INFO')) def delete(self, request, **kwargs): """删除host """ try: models.HostIP.objects.get(id=kwargs['pk']).delete() except ObjectDoesNotExist: return Response(response.HOSTIP_NOT_EXISTS) return Response(response.HOST_DEL_SUCCESS) @method_decorator(request_log(level='DEBUG')) def all(self, request, **kwargs): """ get all config """ pk = kwargs["pk"] queryset = self.get_queryset().filter(project__id=pk). \ order_by('-update_time').values("id", "name") return Response(queryset)
class ScheduleView(GenericViewSet): """ 定时任务增删改查 """ queryset = models.PeriodicTask.objects serializer_class = serializers.PeriodicTaskSerializer pagination_class = pagination.MyPageNumberPagination @method_decorator(request_log(level='DEBUG')) def list(self, request): """ 查询项目信息 """ project = request.query_params.get("project") schedule = self.get_queryset().filter( description=project).order_by('-date_changed') page_schedule = self.paginate_queryset(schedule) serializer = self.get_serializer(page_schedule, many=True) return self.get_paginated_response(serializer.data) @method_decorator(request_log(level='INFO')) def add(self, request): """新增定时任务{ name: str corntab: str switch: bool data: [int,int] strategy: str receiver: str copy: str project: int } """ task = Task(**request.data) resp = task.add_task() return Response(resp) # # @method_decorator(request_log(level='INFO')) # def update(self, request): # """ # 编辑项目 # """ # # try: # project = models.Project.objects.get(id=request.data['id']) # except (KeyError, ObjectDoesNotExist): # return Response(response.SYSTEM_ERROR) # # if request.data['name'] != project.name: # if models.Project.objects.filter(name=request.data['name']).first(): # return Response(response.PROJECT_EXISTS) # # # 调用save方法update_time字段才会自动更新 # project.name = request.data['name'] # project.desc = request.data['desc'] # project.save() # # return Response(response.PROJECT_UPDATE_SUCCESS) # # @method_decorator(request_log(level='INFO')) def delete(self, request, **kwargs): """删除任务 """ task = models.PeriodicTask.objects.get(id=kwargs["pk"]) task.enabled = False task.delete() return Response(response.TASK_DEL_SUCCESS)
class APITemplateView(GenericViewSet): """ API操作视图 """ serializer_class = serializers.APISerializer queryset = models.API.objects schema = APITemplateViewSchema() @swagger_auto_schema(query_serializer=serializers.AssertSerializer) @method_decorator(request_log(level='DEBUG')) def list(self, request): """ api-获取api列表 支持多种条件搜索 """ ser = serializers.AssertSerializer(data=request.query_params) if ser.is_valid(): node = ser.validated_data.get('node') project = ser.validated_data.get('project') search: str = ser.validated_data.get('search') tag = ser.validated_data.get('tag') rig_env = ser.validated_data.get('rigEnv') delete = ser.validated_data.get('delete') only_me = ser.validated_data.get('onlyMe') queryset = self.get_queryset().filter( project__id=project, delete=delete).order_by('-update_time') if only_me is True: queryset = queryset.filter(creator=request.user) if search != '': search: list = search.split() for key in search: queryset = queryset.filter( Q(name__contains=key) | Q(url__contains=key)) if node != '': queryset = queryset.filter(relation=node) if tag != '': queryset = queryset.filter(tag=tag) if rig_env != '': queryset = queryset.filter(rig_env=rig_env) pagination_queryset = self.paginate_queryset(queryset) serializer = self.get_serializer(pagination_queryset, many=True) return self.get_paginated_response(serializer.data) else: return Response(ser.errors, status=status.HTTP_400_BAD_REQUEST) @method_decorator(request_log(level='INFO')) def add(self, request): """ api-新增一个api 前端按照格式组装好,注意body """ api = Format(request.data) api.parse() api_body = { 'name': api.name, 'body': api.testcase, 'url': api.url, 'method': api.method, 'project': models.Project.objects.get(id=api.project), 'relation': api.relation, 'creator': request.user.username } try: models.API.objects.create(**api_body) except DataError: return Response(response.DATA_TO_LONG) return Response(response.API_ADD_SUCCESS) @method_decorator(request_log(level='INFO')) def update(self, request, **kwargs): """ api-更新单个api 更新单个api的内容 """ pk = kwargs['pk'] api = Format(request.data) api.parse() api_body = { 'name': api.name, 'body': api.testcase, 'url': api.url, 'method': api.method, 'updater': request.user.username } try: models.API.objects.filter(id=pk).update(**api_body) except ObjectDoesNotExist: return Response(response.API_NOT_FOUND) return Response(response.API_UPDATE_SUCCESS) @method_decorator(request_log(level='INFO')) def move(self, request): """ api-批量更新api的目录 移动api到指定目录 """ project: int = request.data.get('project') relation: int = request.data.get('relation') apis: list = request.data.get('api') ids = [api['id'] for api in apis] try: models.API.objects.filter(project=project, id__in=ids).update(relation=relation) except ObjectDoesNotExist: return Response(response.API_NOT_FOUND) return Response(response.API_UPDATE_SUCCESS) @method_decorator(request_log(level='INFO')) def copy(self, request, **kwargs): """ api-复制api 复制一个api """ pk = kwargs['pk'] name = request.data['name'] api = models.API.objects.get(id=pk) body = eval(api.body) body["name"] = name api.body = body api.id = None api.name = name api.creator = request.user.username api.updater = request.user.username api.save() return Response(response.API_ADD_SUCCESS) @method_decorator(request_log(level='INFO')) def delete(self, request, **kwargs): """ api-删除一个api 软删除一个api """ try: if kwargs.get('pk'): # 单个删除 # models.API.objects.get(id=kwargs['pk']).delete() models.API.objects.filter(id=kwargs['pk']).update( delete=1, update_time=datetime.datetime.now()) else: for content in request.data: # models.API.objects.get(id=content['id']).delete() models.API.objects.filter(id=content['id']).update( delete=1) except ObjectDoesNotExist: return Response(response.API_NOT_FOUND) return Response(response.API_DEL_SUCCESS) @method_decorator(request_log(level='INFO')) def add_tag(self, request, **kwargs): """ api-更新api的tag,暂时默认为调试成功 更新api的tag类型 """ try: if kwargs.get('pk'): models.API.objects.filter(id=kwargs['pk']).update( tag=request.data['tag'], update_time=datetime.datetime.now(), updater=request.user.username) except ObjectDoesNotExist: return Response(response.API_NOT_FOUND) return Response(response.API_UPDATE_SUCCESS) @method_decorator(request_log(level='INFO')) def sync_case(self, request, **kwargs): """ api-同步api的到case_step 1.根据api_id查出("name", "body", "url", "method") 2.根据api_id更新case_step中的("name", "body", "url", "method", "updater") 3.更新case的update_time, updater """ pk = kwargs['pk'] source_api = models.API.objects.filter(pk=pk).values( "name", "body", "url", "method").first() case_steps = models.CaseStep.objects.filter(source_api_id=pk) case_steps.update(**source_api, updater=request.user.username, update_time=datetime.datetime.now()) case_ids = case_steps.values('case') models.Case.objects.filter(pk__in=case_ids).update( update_time=datetime.datetime.now(), updater=request.user.username) return Response(response.CASE_STEP_SYNC_SUCCESS) @method_decorator(request_log(level='INFO')) def single(self, request, **kwargs): """ api-获取单个api详情,返回body信息 获取单个api的详细情况 """ try: api = models.API.objects.get(id=kwargs['pk']) except ObjectDoesNotExist: return Response(response.API_NOT_FOUND) parse = Parse(eval(api.body)) parse.parse_http() resp = { 'id': api.id, 'body': parse.testcase, 'success': True, } return Response(resp)
class TestCaseView(GenericViewSet): queryset = models.Case.objects serializer_class = serializers.CaseSerializer tag_options = {"冒烟用例": 1, "集成用例": 2, "监控脚本": 3} @method_decorator(request_log(level='INFO')) def get(self, request): """ 查询指定CASE列表,不包含CASE STEP { "project": int, "node": int } """ node = request.query_params["node"] search = request.query_params["search"] # update_time 降序排列 queryset = self.filter_queryset( self.get_queryset()).order_by('-update_time') if search != '': queryset = queryset.filter(name__contains=search) if node != '': queryset = queryset.filter(relation=node) pagination_query = self.paginate_queryset(queryset) serializer = self.get_serializer(pagination_query, many=True) return self.get_paginated_response(serializer.data) @method_decorator(request_log(level='INFO')) def copy(self, request, **kwargs): """ pk int: test id { name: test name relation: int project: int } """ pk = kwargs['pk'] name = request.data['name'] case = models.Case.objects.get(id=pk) case.id = None case.name = name case.save() case_step = models.CaseStep.objects.filter(case__id=pk) for step in case_step: step.id = None step.case = case step.save() return Response(response.CASE_ADD_SUCCESS) @method_decorator(request_log(level='INFO')) def patch(self, request, **kwargs): """ 更新测试用例集 { name: str id: int body: [] project: int } """ pk = kwargs['pk'] project = request.data.pop("project") body = request.data.pop('body') relation = request.data.pop("relation") if models.Case.objects.exclude(id=pk). \ filter(name=request.data['name'], project__id=project, relation=relation).first(): return Response(response.CASE_EXISTS) case = models.Case.objects.get(id=pk) prepare.update_casestep(body, case) request.data['tag'] = self.tag_options[request.data['tag']] models.Case.objects.filter(id=pk).update(**request.data) return Response(response.CASE_UPDATE_SUCCESS) @method_decorator(request_log(level='INFO')) def post(self, request): """ 新增测试用例集 { name: str project: int, relation: int, tag:str body: [{ id: int, project: int, name: str, method: str, url: str }] } """ try: pk = request.data['project'] request.data['project'] = models.Project.objects.get(id=pk) except KeyError: return Response(response.KEY_MISS) except ObjectDoesNotExist: return Response(response.PROJECT_NOT_EXISTS) body = request.data.pop('body') request.data['tag'] = self.tag_options[request.data['tag']] models.Case.objects.create(**request.data) case = models.Case.objects.filter(**request.data).first() prepare.generate_casestep(body, case) return Response(response.CASE_ADD_SUCCESS) @method_decorator(request_log(level='INFO')) def delete(self, request, **kwargs): """ pk: test id delete single [{id:int}] delete batch """ pk = kwargs.get('pk') try: if pk: prepare.case_end(pk) else: for content in request.data: prepare.case_end(content['id']) except ObjectDoesNotExist: return Response(response.SYSTEM_ERROR) return Response(response.CASE_DELETE_SUCCESS)
class TestCaseView(ModelViewSet): """ create:新增测试用例集 { name: str project: int, relation: int, tag:str body: [{ id: int, project: int, name: str }] } create: copy{ id: 36 name: "d" project: 6 relation: 1 } """ serializer_class = serializers.CaseSerializer pagination_class = pagination.MyPageNumberPagination permission_classes = (DjangoModelPermissions,) def get_queryset(self): project = self.request.query_params["project"] queryset = models.Case.objects.filter(project__id=project).order_by('-update_time') if self.action == 'list': node = self.request.query_params["node"] search = self.request.query_params["search"] if search != '': queryset = queryset.filter(name__contains=search) if node != '': queryset = queryset.filter(relation=node) return queryset @method_decorator(request_log(level='INFO')) def create(self, request, *args, **kwargs): if 'id' in request.data.keys(): pk = request.data['id'] name = request.data['name'] case_info = models.Case.objects.get(id=pk) request_data = { "name": name, "relation": case_info.relation, "length": case_info.length, "tag": case_info.tag, "project": case_info.project_id } serializer = self.get_serializer(data=request_data) serializer.is_valid(raise_exception=True) self.perform_create(serializer) case_step = models.CaseStep.objects.filter(case__id=pk) for step in case_step: step.id = None step.case_id = serializer.data["id"] step.save() else: body = request.data.pop('body') serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) self.perform_create(serializer) case = models.Case.objects.filter(**request.data).first() prepare.generate_casestep(body, case) headers = self.get_success_headers(serializer.data) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) @method_decorator(request_log(level='INFO')) def update(self, request, *args, **kwargs): body = request.data.pop('body') partial = kwargs.pop('partial', False) instance = self.get_object() serializer = self.get_serializer(instance, data=request.data, partial=partial) serializer.is_valid(raise_exception=True) prepare.update_casestep(body, instance) self.perform_update(serializer) if getattr(instance, '_prefetched_objects_cache', None): # If 'prefetch_related' has been applied to a queryset, we need to # forcibly invalidate the prefetch cache on the instance. instance._prefetched_objects_cache = {} return Response(serializer.data) @method_decorator(request_log(level='INFO')) def destroy(self, request, *args, **kwargs): if kwargs.get('pk') and int(kwargs['pk']) != -1: instance = self.get_object() prepare.case_end(int(kwargs['pk'])) self.perform_destroy(instance) elif request.data: for content in request.data: self.kwargs['pk'] = content['id'] instance = self.get_object() prepare.case_end(int(kwargs['pk'])) self.perform_destroy(instance) return Response(status=status.HTTP_204_NO_CONTENT) @method_decorator(request_log(level='INFO')) def retrieve(self, request, *args, **kwargs): instance = self.get_object() serializer = self.get_serializer(instance) queryset = models.CaseStep.objects.filter(case__id=kwargs['pk']).order_by('step') casestep_serializer = serializers.CaseStepSerializer(queryset, many=True) resp = { "case": serializer.data, "step": casestep_serializer.data } return Response(resp)
class ScheduleView(GenericViewSet): """ 定时任务增删改查 """ queryset = models.PeriodicTask.objects serializer_class = serializers.PeriodicTaskSerializer pagination_class = pagination.MyPageNumberPagination @method_decorator(request_log(level='DEBUG')) def list(self, request): """ 查询项目信息 """ project = request.query_params.get("project") schedule = self.get_queryset().filter(description=project).order_by('-date_changed') page_schedule = self.paginate_queryset(schedule) serializer = self.get_serializer(page_schedule, many=True) return self.get_paginated_response(serializer.data) @method_decorator(request_log(level='INFO')) def add(self, request): """新增定时任务{ name: str crontab: str switch: bool data: [int,int] strategy: str receiver: str copy: str project: int } """ request.data.update({"creator": request.user.username}) task = Task(**request.data) resp = task.add_task() return Response(resp) @method_decorator(request_log(level='INFO')) def update(self, request, **kwargs): """更新任务 :param request: :param kwargs: :return: """ task = Task(**request.data) resp = task.update_task(kwargs['pk']) return Response(resp) @method_decorator(request_log(level='INFO')) def patch(self, request, **kwargs): """更新任务的状态 :param request: :param kwargs: :return: """ # {'pk': 22} task_obj = self.get_queryset().get(pk=kwargs['pk']) task_obj.enabled = request.data['switch'] kwargs = json.loads(task_obj.kwargs) kwargs['updater'] = request.user.username task_obj.kwargs = json.dumps(kwargs, ensure_ascii=False) task_obj.save() return Response(response.TASK_UPDATE_SUCCESS) def delete(self, request, **kwargs): """删除任务 """ task = models.PeriodicTask.objects.get(id=kwargs["pk"]) task.enabled = False task.delete() return Response(response.TASK_DEL_SUCCESS) @method_decorator(request_log(level='INFO')) def run(self, request, **kwargs): task = models.PeriodicTask.objects.get(id=kwargs["pk"]) task_name = 'fastrunner.tasks.schedule_debug_suite' args = eval(task.args) kwargs = eval(task.kwargs) app.send_task(name=task_name, args=args, kwargs=kwargs) return Response(response.TASK_RUN_SUCCESS)
class TestCaseView(GenericViewSet): queryset = models.Case.objects serializer_class = serializers.CaseSerializer tag_options = { "冒烟用例": 1, "集成用例": 2, "监控脚本": 3 } @staticmethod def case_step_search(search): """ 搜索case_step的url或者name 返回对应的case_id """ case_id = models.CaseStep.objects.filter(Q(name__contains=search) | Q(url__contains=search)).values('case_id') case_id = set([item['case_id'] for _, item in enumerate(case_id)]) return case_id @method_decorator(request_log(level='INFO')) def get(self, request): """ 查询指定CASE列表,不包含CASE STEP { "project": int, "node": int } """ ser = serializers.CaseSearchSerializer(data=request.query_params) if ser.is_valid(): node = ser.validated_data.get("node") project = ser.validated_data.get("project") search = ser.validated_data.get("search") search_type = ser.validated_data.get("searchType") case_type = ser.validated_data.get("caseType") only_me = ser.validated_data.get("onlyMe") # update_time 降序排列 queryset = self.get_queryset().filter(project__id=project).order_by('-update_time') if only_me is True: queryset = queryset.filter(creator=request.user) if node != '': queryset = queryset.filter(relation=node) if case_type != '': queryset = queryset.filter(tag=case_type) if search != '': # 用例名称搜索 if search_type == '1': queryset = queryset.filter(name__contains=search) # API名称或者API URL搜索 elif search_type == '2': case_id = self.case_step_search(search) queryset = queryset.filter(pk__in=case_id) pagination_query = self.paginate_queryset(queryset) serializer = self.get_serializer(pagination_query, many=True) return self.get_paginated_response(serializer.data) else: return Response(ser.errors, status=status.HTTP_400_BAD_REQUEST) @method_decorator(request_log(level='INFO')) def copy(self, request, **kwargs): """ pk int: test id { name: test name relation: int project: int } """ pk = kwargs['pk'] name = request.data['name'] username = request.user.username tree_id = request.data['treeId'] pro_id = request.data['projectId'] if '|' in name: resp = self.split(pk, name) else: for tree in tree_id: case = models.Case.objects.get(id=pk) case.id = None case.name = name case.creator = username case.updater = username case.relation = tree case.project_id = pro_id case.save() case_step = models.CaseStep.objects.filter(case__id=pk) for step in case_step: step.id = None step.case = case step.creator = username step.updater = username step.save() resp = response.CASE_ADD_SUCCESS return Response(resp)
class ProjectView(ModelViewSet): """ 项目增删改查 """ serializer_class = serializers.ProjectSerializer pagination_class = pagination.MyCursorPagination permission_classes = (DjangoModelPermissions, IsBelongToProject) def get_queryset(self): if self.request.user.is_superuser: return models.Project.objects.annotate( count=Count("api")).all().order_by('-create_time') project_id_list = UserModel.objects.filter( id=self.request.user.id).values_list('belong_project', flat=True) return models.Project.objects.filter( id__in=[_ for _ in project_id_list]).annotate( count=Count("api")).all().order_by('-update_time') @method_decorator(request_log(level='INFO')) def single(self, request, **kwargs): """ 得到单个项目相关统计信息 """ pk = kwargs.pop('pk') try: queryset = models.Project.objects.get(id=pk) except ObjectDoesNotExist: return Response(response.PROJECT_NOT_EXISTS) serializer = self.get_serializer(queryset, many=False) project_info = prepare.get_project_detail(pk) project_info.update(serializer.data) return Response(project_info) def perform_create(self, serializer): instance = serializer.save() # 生成debugtalk.py文件 models.Pycode.objects.create(project=instance, name="debugtalk.py", desc="项目的根目录文件,项目中所使用函数都从此中调用") models.Pycode.objects.create(project=instance, name="get_excel_data.py", desc="获取excel表格数据", code=""" # _*_ coding:utf-8 _*_ import xlrd import os class Xlaccountinfo(): # 获取excel数据,从第三行开始,第二行是表头,第一行是备注 def __init__(self, path=''): self.xl = xlrd.open_workbook(path) def floattostr(self, val): if isinstance(val, float) and float(int(val)) != val: val = str(int(val)) if val.lower() == 'true': val = True elif val.lower() == 'false': val = False return val def get_sheetinfo_by_name(self, name): self.sheet = self.xl.sheet_by_name(name) return self.get_sheet_info() def get_sheetinfo_by_index(self, index): self.sheet = self.xl.sheet_by_index(index) return self.get_sheet_info() def get_sheetinfo_by_rowName(self, name): self.sheet = self.xl.sheet_by_name(name) infolist = [] for col in range(self.sheet.ncols): if col == 0: listKey = [self.floattostr(val.strip()) for val in self.sheet.col_values(col)] elif col == 1: info = [self.floattostr(val.strip()) for val in self.sheet.col_values(col)] tmp = zip(listKey, info) infolist.append(dict(tmp)) return infolist def get_sheet_info(self): infolist = [] for row in range(1, self.sheet.nrows): if row == 1: listKey = [self.floattostr(val.strip()) for val in self.sheet.row_values(row)] else: info = [self.floattostr(val.strip()) for val in self.sheet.row_values(row)] tmp = zip(listKey, info) infolist.append(dict(tmp)) return infolist # 通过行获取excel数据 def get_xlsx_by_cols(excelName, sheetName): xlinfo = Xlaccountinfo(excelName) info = xlinfo.get_sheetinfo_by_name(sheetName) return info # 通过列获取excel数据 def xlsxPlatform(excelName, sheetName): xlinfo = Xlaccountinfo(excelName) info = xlinfo.get_sheetinfo_by_rowName(sheetName) return info if __name__ == '__main__': excelName = os.environ["excelName"] sheetName = os.environ["excelsheet"] """) # 自动生成API tree models.Relation.objects.create(project=instance) # 自动生成Test Tree models.Relation.objects.create(project=instance, type=2) # 自动生成 TestData Tree models.Relation.objects.create(project=instance, type=3) def perform_destroy(self, instance): project_id = instance.id celery_models.PeriodicTask.objects.filter( description=project_id).delete() instance.delete()
class TreeView(GenericViewSet): """ 树形结构操作 """ permission_classes = (DjangoModelPermissions, IsBelongToProject) def get_queryset(self): project_id = self.kwargs.get('pk') queryset = models.Relation.objects.filter( project__id=project_id).order_by('-update_time') return queryset @method_decorator(request_log(level='INFO')) def get(self, request, **kwargs): """ 返回树形结构 当前最带节点ID """ try: tree_type = request.query_params['type'] except KeyError: return Response(response.KEY_MISS) try: tree = models.Relation.objects.get(project_id=kwargs['pk'], type=tree_type) body = eval(tree.tree) except ObjectDoesNotExist as e: tree = models.Relation.objects.create(project_id=kwargs['pk'], type=tree_type, tree=[{ 'id': 1, 'label': 'testdata', 'children': [] }]) body = [] tree = { "tree": body, "id": tree.id, "success": True, "max": get_tree_max_id(body) } return Response(tree) @method_decorator(request_log(level='INFO')) def patch(self, request, **kwargs): """ 修改树形结构,ID不能重复 """ try: body = request.data['body'] mode = request.data['mode'] relation = models.Relation.objects.get(id=kwargs['pk']) relation.tree = body relation.save() except KeyError: return Response(response.KEY_MISS) except ObjectDoesNotExist: return Response(response.SYSTEM_ERROR) # mode -> True remove node if mode: prepare.tree_end(request.data, relation.project) response.TREE_UPDATE_SUCCESS['tree'] = body response.TREE_UPDATE_SUCCESS['max'] = get_tree_max_id(body) return Response(response.TREE_UPDATE_SUCCESS)
class APITemplateView(GenericViewSet): """ API操作视图 """ serializer_class = serializers.APISerializer queryset = models.API.objects permission_classes = (DjangoModelPermissions, ) @method_decorator(request_log(level='DEBUG')) def list(self, request): """ 接口列表 { project: int, node: int } """ node = request.query_params["node"] project = request.query_params["project"] search = request.query_params["search"] queryset = self.get_queryset().filter( project__id=project).order_by('-update_time') if search != '': queryset = queryset.filter(name__contains=search) if node != '': queryset = queryset.filter(relation=node) pagination_queryset = self.paginate_queryset(queryset) serializer = self.get_serializer(pagination_queryset, many=True) return self.get_paginated_response(serializer.data) @method_decorator(request_log(level='INFO')) def add(self, request): """ 新增一个接口 """ api = Format(request.data) api.parse() api_body = { 'name': api.name, 'body': api.testcase, 'url': api.url, 'method': api.method, 'project': models.Project.objects.get(id=api.project), 'relation': api.relation } try: models.API.objects.create(**api_body) except DataError: return Response(response.DATA_TO_LONG) return Response(response.API_ADD_SUCCESS) @method_decorator(request_log(level='INFO')) def update(self, request, **kwargs): """ 更新接口 更新接口时同时更新testcase中的case_step的request和header """ pk = kwargs['pk'] api = Format(request.data) api.parse() api_body = { 'name': api.name, 'body': api.testcase, 'url': api.url, 'method': api.method, } try: models.API.objects.filter(id=pk).update(**api_body) case_step = models.CaseStep.objects.filter(apiId=pk) for case in case_step: csae_body = eval(case.body) csae_body["request"] = api_body["body"]["request"] csae_body["desc"]["header"] = api_body["body"]["desc"][ "header"] csae_body["desc"]["data"] = api_body["body"]["desc"]["data"] csae_body["desc"]["files"] = api_body["body"]["desc"]["files"] csae_body["desc"]["params"] = api_body["body"]["desc"][ "params"] case.url = api_body["url"] case.method = api_body["method"] case.body = csae_body case.save() except ObjectDoesNotExist: return Response(response.API_NOT_FOUND) return Response(response.API_UPDATE_SUCCESS) @method_decorator(request_log(level='INFO')) def copy(self, request, **kwargs): """ pk int: test id { name: api name } """ pk = kwargs['pk'] name = request.data['name'] api = models.API.objects.get(id=pk) body = eval(api.body) body["name"] = name api.body = body api.id = None api.name = name api.save() return Response(response.API_ADD_SUCCESS) @method_decorator(request_log(level='INFO')) def delete(self, request, **kwargs): """ 删除一个接口 pk 删除多个 [{ id:int }] """ try: if kwargs.get('pk'): # 单个删除 models.API.objects.get(id=kwargs['pk']).delete() else: for content in request.data: models.API.objects.get(id=content['id']).delete() except ObjectDoesNotExist: return Response(response.API_NOT_FOUND) return Response(response.API_DEL_SUCCESS) @method_decorator(request_log(level='INFO')) def single(self, request, **kwargs): """ 查询单个api,返回body信息 """ try: api = models.API.objects.get(id=kwargs['pk']) except ObjectDoesNotExist: return Response(response.API_NOT_FOUND) parse = Parse(eval(api.body)) parse.parse_http() resp = { 'id': api.id, 'body': parse.testcase, 'success': True, } return Response(resp)
class ReportView(GenericViewSet): """ 报告视图 """ authentication_classes = () queryset = models.Report.objects serializer_class = serializers.ReportSerializer pagination_class = pagination.MyPageNumberPagination @method_decorator(request_log(level='DEBUG')) def list(self, request): """报告列表 """ project = request.query_params['project'] search = request.query_params["search"] queryset = self.get_queryset().filter( project__id=project).order_by('-update_time') if search != '': queryset = queryset.filter(name__contains=search) page_report = self.paginate_queryset(queryset) serializer = self.get_serializer(page_report, many=True) return self.get_paginated_response(serializer.data) @method_decorator(request_log(level='INFO')) def delete(self, request, **kwargs): """删除报告 """ """ 删除一个报告pk 删除多个 [{ id:int }] """ try: if kwargs.get('pk'): # 单个删除 models.Report.objects.get(id=kwargs['pk']).delete() else: for content in request.data: models.Report.objects.get(id=content['id']).delete() except ObjectDoesNotExist: return Response(response.REPORT_NOT_EXISTS) return Response(response.REPORT_DEL_SUCCESS) @method_decorator(request_log(level='INFO')) def look(self, request, **kwargs): """查看报告 """ pk = kwargs["pk"] report = models.Report.objects.get(id=pk) summary = json.loads(report.summary, encoding="utf-8") summary["html_report_name"] = report.name return render_to_response('report_template.html', summary) def download(self, request, **kwargs): """下载报告 """ pass
class ScheduleView(ModelViewSet): """ 定时任务增删改查 """ serializer_class = serializers.PeriodicTaskSerializer pagination_class = pagination.MyPageNumberPagination permission_classes = (DjangoModelPermissions, ) def get_queryset(self): project = self.request.query_params.get("project") return celery_models.PeriodicTask.objects.filter( description=project).order_by('-date_changed') @method_decorator(request_log(level='INFO')) def create(self, request, *args, **kwargs): """新增定时任务{ name: str corntab: str switch: bool data: [{kwargs: dict,} ,] strategy: str receiver: str copy: str project: int, } """ if 'id' in request.data.keys(): pk = request.data['id'] name = request.data['name'] periodic_info = self.get_queryset().get(id=pk) request_data = { "name": name, "task": "fastrunner.tasks.schedule_debug_suite", "crontab": periodic_info.crontab_id, "args": periodic_info.args, "kwargs": periodic_info.kwargs, "description": periodic_info.description, "enabled": periodic_info.enabled } else: request_data = format_request(request.data) if not request_data["kwargs"]["receiver"]["success"]: return Response(request_data["_email"]["receiver"]["error"], status=status.HTTP_400_BAD_REQUEST) if not request_data["kwargs"]["mail_cc"]["success"]: return Response(request_data["_email"]["mail_cc"]["error"], status=status.HTTP_400_BAD_REQUEST) if request_data["kwargs"]["strategy"] in [ '始终发送', '仅失败发送' ] and request_data["kwargs"]["receiver"] == []: return Response({"receiver": "请填写接收邮箱"}, status=status.HTTP_400_BAD_REQUEST) if not request_data["crontab"]["success"]: return Response(request_data["crontab"]["error"], status=status.HTTP_400_BAD_REQUEST) crontab = celery_models.CrontabSchedule.objects.filter( **request_data["crontab"]["crontab"]).first() if crontab is None: crontab = serializers.CrontabScheduleSerializer( data=request_data["crontab"]["crontab"]) crontab.is_valid(raise_exception=True) crontab.save() crontab = celery_models.CrontabSchedule.objects.filter( **request_data["crontab"]["crontab"]).first() request_data["crontab"] = crontab.id request_data["kwargs"]["receiver"] = request_data["kwargs"][ "receiver"]["email"] request_data["kwargs"]["mail_cc"] = request_data["kwargs"][ "mail_cc"]["email"] request_data["kwargs"] = json.dumps(request_data["kwargs"], ensure_ascii=False) serializer = self.get_serializer(data=request_data) serializer.is_valid(raise_exception=True) self.perform_create(serializer) headers = self.get_success_headers(serializer.data) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) @method_decorator(request_log(level='INFO')) def update(self, request, *args, **kwargs): partial = kwargs.pop('partial', False) instance = self.get_object() request_data = format_request(request.data) if not request_data["kwargs"]["receiver"]["success"]: return Response(request_data["kwargs"]["receiver"]["error"], status=status.HTTP_400_BAD_REQUEST) if not request_data["kwargs"]["mail_cc"]["success"]: return Response(request_data["kwargs"]["mail_cc"]["error"], status=status.HTTP_400_BAD_REQUEST) if request_data["kwargs"]["strategy"] in [ '始终发送', '仅失败发送' ] and request_data["kwargs"]["receiver"] == []: return Response({"receiver": "请填写接收邮箱"}, status=status.HTTP_400_BAD_REQUEST) if not request_data["crontab"]["success"]: return Response(request_data["crontab"]["error"], status=status.HTTP_400_BAD_REQUEST) crontab = celery_models.CrontabSchedule.objects.filter( **request_data["crontab"]["crontab"]).first() if crontab is None: crontab = serializers.CrontabScheduleSerializer( data=request_data["crontab"]["crontab"]) crontab.is_valid(raise_exception=True) crontab.save() crontab = celery_models.CrontabSchedule.objects.filter( **request_data["crontab"]["crontab"]).first() request_data["crontab"] = crontab.id request_data["kwargs"]["receiver"] = request_data["kwargs"][ "receiver"]["email"] request_data["kwargs"]["mail_cc"] = request_data["kwargs"]["mail_cc"][ "email"] request_data["kwargs"] = json.dumps(request_data["kwargs"], ensure_ascii=False) serializer = self.get_serializer(instance, data=request_data, partial=partial) serializer.is_valid(raise_exception=True) self.perform_update(serializer) if getattr(instance, '_prefetched_objects_cache', None): # If 'prefetch_related' has been applied to a queryset, we need to # forcibly invalidate the prefetch cache on the instance. instance._prefetched_objects_cache = {} return Response(serializer.data) def destroy(self, request, *args, **kwargs): if kwargs.get('pk') and int(kwargs['pk']) != -1: instance = self.get_object() self.perform_destroy(instance) elif request.data: for content in request.data: self.kwargs['pk'] = content['id'] instance = self.get_object() self.perform_destroy(instance) return Response(status=status.HTTP_204_NO_CONTENT)
class ReportView(GenericViewSet): """ 报告视图 """ queryset = models.Report.objects serializer_class = serializers.ReportSerializer pagination_class = pagination.MyPageNumberPagination def get_authenticators(self): # 查看报告详情不需要鉴权 # self.request.path = '/api/fastrunner/reports/3053/' pattern = re.compile(r'/api/fastrunner/reports/\d+/') if self.request.method == 'GET' and re.search( pattern, self.request.path) is not None: return [] return super().get_authenticators() @method_decorator(request_log(level='DEBUG')) def list(self, request): """报告列表 """ project = request.query_params['project'] search = request.query_params["search"] report_type = request.query_params["reportType"] report_status = request.query_params["reportStatus"] only_me = request.query_params["onlyMe"] queryset = self.get_queryset().filter( project__id=project).order_by('-update_time') # 前端传过来是小写的字符串,不是python的True if only_me == 'true': queryset = queryset.filter(creator=request.user) if search != '': queryset = queryset.filter(name__contains=search) if report_type != '': queryset = queryset.filter(type=report_type) if report_status != '': queryset = queryset.filter(status=report_status) page_report = self.paginate_queryset(queryset) serializer = self.get_serializer(page_report, many=True) return self.get_paginated_response(serializer.data) @method_decorator(request_log(level='INFO')) def delete(self, request, **kwargs): """删除报告 """ """ 删除一个报告pk 删除多个 [{ id:int }] """ try: if kwargs.get('pk'): # 单个删除 models.Report.objects.get(id=kwargs['pk']).delete() else: for content in request.data: models.Report.objects.get(id=content['id']).delete() except ObjectDoesNotExist: return Response(response.REPORT_NOT_EXISTS) return Response(response.REPORT_DEL_SUCCESS) @method_decorator(request_log(level='INFO')) def look(self, request, **kwargs): """查看报告 """ pk = kwargs["pk"] report = models.Report.objects.get(id=pk) report_detail = models.ReportDetail.objects.get(report_id=pk) summary = json.loads(report.summary, encoding="utf-8") summary['details'] = str(report_detail.summary_detail).replace( 'Markup', '').replace('\\n', '').replace(" ", "").replace(""", "\"") summary['details'] = eval(summary['details']) print(summary) summary["html_report_name"] = report.name # return render_to_response('report_template.html', summary) return render(request, template_name='report_template.html', context=summary) def download(self, request, **kwargs): """下载报告 """ pass
class APIRigView(GenericViewSet): authentication_classes = [] serializer_class = serializers.APISerializer queryset = models.API.objects def list(self, request): """ 接口列表 { project: int, node: int } """ node = request.query_params["node"] project = request.query_params["project"] search = request.query_params["search"] # queryset = self.get_queryset().filter(project__id=project).order_by('-update_time') queryset = self.get_queryset().filter( project__id=project, delete=0).order_by('-update_time') # queryset = self.get_queryset().filter(Q(project__id=project) and ~Q(delete=1)).order_by('-update_time') if search != '': queryset = queryset.filter(name__contains=search) if node != '': queryset = queryset.filter(relation=node) pagination_queryset = self.paginate_queryset(queryset) serializer = self.get_serializer(pagination_queryset, many=True) return self.get_paginated_response(serializer.data) @method_decorator(request_log(level='INFO')) def add(self, request): """ 新增一个接口 { "header": { "header": { "wb-token": "$wb_token" }, "desc": { "wb-token": "用户登陆token" } }, "request": { "form": { "data": {}, "desc": {} }, "json": {}, "params": { "params": { "goodsCode": "42470" }, "desc": { "goodsCode": "商品编码" } }, "files": { "files": {}, "desc": {} } }, "extract": { "extract": [], "desc": {} }, "validate": { "validate": [{"equals": ["content.info.error",0]}] }, "variables": { "variables": [ { "auth_type": "APP_MEMBER_AUTH" }, { "rpc_Group": "wbiao.seller.prod" }, { "rpc_Interface": "cn.wbiao.seller.api.GoodsDetailService" }, { "params_type": "Key_Value" }, { "author": "xuqirong" } ], "desc": { "auth_type": "认证类型", "rpc_Group": "RPC服务组", "rpc_Interface": "后端服务接口", "params_type": "入参数形式", "author": "作者" } }, "hooks": { "setup_hooks": [ "${get_sign($request,$auth_type)}" ], "teardown_hooks": [] }, "url": "/wxmp/mall/goods/detail/getRecommendGoodsList", "method": "GET", "name": "查询关联的商品推荐列表-小程序需签名", "times": 1, "nodeId": "member", "project": 5, "rig_id":200014 } """ api = Format(request.data) api.parse() # try: # rig_env = api.rig_env # except KeyError: # # 不传环境,使用默认测试环境0 # rig_env = 0 try: relation = API_RELATION[api.relation] except KeyError: relation = API_RELATION['default'] if api.rig_id: api.name = api.name + '-' + str(api.rig_id) if api.rig_env == 0: api.name += '-测试' elif api.rig_env == 1: api.name += '-生产' # 生产环境比测试环境的关系节点大20 relation += 20 else: api.name += '-预发布' api.testcase['name'] = api.name api_body = { 'name': api.name, 'body': api.testcase, 'url': api.url, 'method': api.method, 'project': models.Project.objects.get(id=api.project), # 'relation': api.relation, 'rig_id': api.rig_id, 'rig_env': api.rig_env, 'relation': relation } # try: # relation = API_RELATION[api.relation] # except KeyError: # relation = API_RELATION['default'] # api_body['relation'] = relation try: # 增加api之前先删除已经存在的相同id的除了手动调试成功的api models.API.objects.filter( rig_id=api.rig_id).filter(~Q(tag=1)).update( delete=1, update_time=datetime.datetime.now()) # 创建成功,返回对象,方便获取id obj = models.API.objects.create(**api_body) except DataError: return Response(response.DATA_TO_LONG) # api作者 # 2019年10月22日 修复rig增加api运行失败时,没有复制api到Java同学项目 author = api_body['body']['variables'][4]['author'] self.copy_to_java(api.rig_id, author) # api运行成功,就自动增加到用例集里面 run_result = run.auto_run_api_pk(config=api.rig_env, id=obj.id) if run_result == 'success': run.update_auto_case_step(**api_body) return Response(response.API_ADD_SUCCESS) # 复制一份到Java同学项目 def copy_to_java(self, rig_id, author): # 根据作者决定分组 try: relation = API_AUTHOR[author] except KeyError: relation = API_AUTHOR['default'] # Java项目的id=4 # obj = models.API.objects.get(rig_id=rig_id) # 修复已经存在的rig_id的api无法复制 obj = models.API.objects.filter(rig_id=rig_id).order_by('-id')[0] obj.id = None obj.relation = relation obj.project_id = 4 obj.save() @method_decorator(request_log(level='INFO')) def update(self, request, **kwargs): """ 更新接口 """ pk = kwargs['rig_id'] api = Format(request.data) api.parse() api_body = { 'name': api.name, 'body': api.testcase, 'url': api.url, 'method': api.method, } try: models.API.objects.filter(rig_id=pk).update(**api_body) except ObjectDoesNotExist: return Response(response.API_NOT_FOUND) return Response(response.API_UPDATE_SUCCESS)
class TestSuiteView(GenericViewSet): queryset = models.TestSuite.objects serializer_class = serializers.TestSuiteSerializer tag_options = { "冒烟用例集": 1, "集成用例集": 2, "监控脚本": 3 } @staticmethod def testsuite_step_search(search): """ 搜索case_step的url或者name 返回对应的case_id """ case_id = models.TestSuiteStep.objects.filter(Q(name__contains=search) | Q(url__contains=search)).values('case_id') case_id = set([item['case_id'] for _, item in enumerate(case_id)]) return case_id @method_decorator(request_log(level='INFO')) def get(self, request): """ 查询指定CASE列表,不包含CASE STEP { "project": int, "node": int } """ ser = serializers.TestSuiteSearchSerializer(data=request.query_params) if ser.is_valid(): node = ser.validated_data.get("node") project = ser.validated_data.get("project") search = ser.validated_data.get("search") search_type = ser.validated_data.get("searchType") case_type = ser.validated_data.get("caseType") only_me = ser.validated_data.get("onlyMe") # update_time 降序排列 queryset = self.get_queryset().filter(project__id=project).order_by('-update_time') if only_me is True: queryset = queryset.filter(creator=request.user) if node != '': queryset = queryset.filter(relation=node) if case_type != '': queryset = queryset.filter(tag=case_type) if search != '': # 用例集名称搜索 if search_type == '1': queryset = queryset.filter(name__contains=search) # API名称或者API URL搜索 elif search_type == '2': case_id = self.testsuite_step_search(search) queryset = queryset.filter(pk__in=case_id) pagination_query = self.paginate_queryset(queryset) serializer = self.get_serializer(pagination_query, many=True) return self.get_paginated_response(serializer.data) else: return Response(ser.errors, status=status.HTTP_400_BAD_REQUEST)
class APITemplateView(GenericViewSet): """ API操作视图 """ serializer_class = serializers.APISerializer queryset = models.API.objects permission_classes = (DjangoModelPermissions, IsBelongToProject) @method_decorator(request_log(level='DEBUG')) def list(self, request): """ 接口列表 { project: int, node: int } """ node = request.query_params["node"] project = request.query_params["project"] search = request.query_params["search"] queryset = self.get_queryset().filter( project__id=project).order_by('-update_time') if search != '': # queryset = queryset.filter(name__contains=search) queryset = queryset.filter( Q(name__contains=search) | Q(url__contains=search)) if node != '': queryset = queryset.filter(relation=node) pagination_queryset = self.paginate_queryset(queryset) serializer = self.get_serializer(pagination_queryset, many=True) return self.get_paginated_response(serializer.data) @method_decorator(request_log(level='INFO')) def add(self, request): """添加或更新一个或多个接口 """ add_apis = [] if request.data.get("bulk_add"): project_id = int(request.data.get("project")) node_id = int(request.data.get("nodeId")) temps = request.data.get("interfaces", {}) for temp in temps.values(): id = temp.get('id', 0) temp.update({"project": project_id, "nodeId": node_id}) api = Format(temp) api.parse() api_body = { 'name': api.name, 'body': api.testcase, 'url': api.url, 'method': api.method, 'project': models.Project.objects.get(id=api.project), 'relation': api.relation } obj = models.API.objects.filter(id=id, relation=node_id, project=project_id) if obj: obj.update(**api_body) else: add_apis.append(models.API(**api_body)) else: api = Format(request.data) api.parse() api_body = { 'name': api.name, 'body': api.testcase, 'url': api.url, 'method': api.method, 'project': models.Project.objects.get(id=api.project), 'relation': api.relation } add_apis.append(models.API(**api_body)) try: if len(add_apis): models.API.objects.bulk_create(add_apis) except DataError: return Response(response.DATA_TO_LONG) except Exception as e: return Response({"error": str(e)}) return Response(response.API_ADD_SUCCESS) @method_decorator(request_log(level='INFO')) def update(self, request, **kwargs): """ 更新接口 """ pk = kwargs['pk'] api = Format(request.data) api.parse() api_body = { 'name': api.name, 'body': api.testcase, 'url': api.url, 'method': api.method, } try: models.API.objects.filter(id=pk).update(**api_body) except ObjectDoesNotExist: return Response(response.API_NOT_FOUND) return Response(response.API_UPDATE_SUCCESS) @method_decorator(request_log(level='INFO')) def copy(self, request, **kwargs): """ pk int: test id { name: api name } """ pk = kwargs['pk'] name = request.data['name'] api = models.API.objects.get(id=pk) body = eval(api.body) body["name"] = name api.body = body api.id = None api.name = name api.save() return Response(response.API_ADD_SUCCESS) @method_decorator(request_log(level='INFO')) def move(self, request, **kwargs): """移动接口到新的node """ relation_id = request.data.get('relation') ids = request.data.get('ids', []) success, failure = [], [] for id in ids: try: api = models.API.objects.get(id=id) api.relation = int(relation_id) api.save() success.append(id) except: failure.append(id) result = { 'relation': relation_id, "success": success, 'failure': failure } ret = response.API_MOVE_SUCCESS ret.update(result=result) return Response(ret) @method_decorator(request_log(level='INFO')) def delete(self, request, **kwargs): """ 删除一个接口 pk 删除多个 [{ id:int }] """ try: if kwargs.get('pk'): # 单个删除 api_end(kwargs['pk']) else: for content in request.data: api_end(content['id']) except ObjectDoesNotExist: return Response(response.API_NOT_FOUND) return Response(response.API_DEL_SUCCESS) @method_decorator(request_log(level='INFO')) def single(self, request, **kwargs): """ 查询单个api,返回body信息 """ try: api = models.API.objects.get(id=kwargs['pk']) except ObjectDoesNotExist: return Response(response.API_NOT_FOUND) parse = Parse(eval(api.body)) parse.parse_http() resp = { 'id': api.id, 'body': parse.testcase, 'success': True, } return Response(resp)
class ProjectView(GenericViewSet): """ 项目增删改查 """ queryset = models.Project.objects.all().order_by('-update_time') serializer_class = serializers.ProjectSerializer pagination_class = pagination.MyCursorPagination @method_decorator(request_log(level='DEBUG')) def list(self, request): """ 查询项目信息 """ projects = self.get_queryset() page_projects = self.paginate_queryset(projects) serializer = self.get_serializer(page_projects, many=True) return self.get_paginated_response(serializer.data) @method_decorator(request_log(level='INFO')) def add(self, request): """添加项目 { name: str } """ name = request.data["name"] if models.Project.objects.filter(name=name).first(): response.PROJECT_EXISTS["name"] = name return Response(response.PROJECT_EXISTS) # 反序列化 serializer = serializers.ProjectSerializer(data=request.data) if serializer.is_valid(): serializer.save() project = models.Project.objects.get(name=name) prepare.project_init(project) return Response(response.PROJECT_ADD_SUCCESS) return Response(response.SYSTEM_ERROR) @method_decorator(request_log(level='INFO')) def update(self, request): """ 编辑项目 """ try: project = models.Project.objects.get(id=request.data['id']) except (KeyError, ObjectDoesNotExist): return Response(response.SYSTEM_ERROR) if request.data['name'] != project.name: if models.Project.objects.filter( name=request.data['name']).first(): return Response(response.PROJECT_EXISTS) # 调用save方法update_time字段才会自动更新 project.name = request.data['name'] project.desc = request.data['desc'] project.responsible = request.data['responsible'] project.yapi_base_url = request.data['yapi_base_url'] project.yapi_openapi_token = request.data['yapi_openapi_token'] project.save() return Response(response.PROJECT_UPDATE_SUCCESS) @method_decorator(request_log(level='INFO')) def delete(self, request): """ 删除项目 """ if request.user.is_superuser is False: return Response(status=status.HTTP_401_UNAUTHORIZED) try: project = models.Project.objects.get(id=request.data['id']) project.delete() prepare.project_end(project) return Response(response.PROJECT_DELETE_SUCCESS) except ObjectDoesNotExist: return Response(response.SYSTEM_ERROR) @method_decorator(request_log(level='INFO')) def single(self, request, **kwargs): """ 得到单个项目相关统计信息 """ pk = kwargs.pop('pk') try: queryset = models.Project.objects.get(id=pk) except ObjectDoesNotExist: return Response(response.PROJECT_NOT_EXISTS) serializer = self.get_serializer(queryset, many=False) project_info = prepare.get_project_detail(pk) project_info.update(serializer.data) return Response(project_info)