Django实现接口自动化平台(十四)测试用例模块Testcases序列化器及视图【持续更新中】

相关文章:

Django实现接口自动化平台(十三)接口模块Interfaces序列化器及视图【持续更新中】_做测试的喵酱的博客-CSDN博客

本章是项目的一个分解,查看本章内容时,要结合整体项目代码来看:

python django vue httprunner 实现接口自动化平台(最终版)_python+vue自动化测试平台_做测试的喵酱的博客-CSDN博客

一、Testcases应用及相关接口

|--------|----------------------|-------------------|-------------------|
| 请求方式 | URI | 对应action | 实现功能 |
| GET | /testcases/ | .list() | 查询testcase列表 |
| POST | /testcases/ | .create() | 创建一条数据 |
| GET | /testcases/{id}/ | .retrieve() | 检索一条testcase的详细数据 |
| PUT | /testcases/{id}/ | update() | 更新一条数据中的全部字段 |
| PATCH | /testcases/{id}/ | .partial_update() | 更新一条数据中的部分字段 |
| DELETE | /testcases/{id}/ | .destroy() | 删除一条数据 |
| POST | /testcases/{id}/run/ | | 运行某个接口下的所有case |

1.1 用例列表

|-----|-------------|---------|--------------|
| GET | /testcases/ | .list() | 查询testcase列表 |

1.2 创建用例

1.2.1 基本信息

1、拉取了项目列表

2、拉取了项目下的接口列表

3、前置用例列表

4、拉取了所有的配置列表

1.2.2 基本信息

二、模型类

python 复制代码
from django.db import models

from utils.base_models import BaseModel


class Interfaces(BaseModel):
    id = models.AutoField(verbose_name='id主键', primary_key=True, help_text='id主键')
    name = models.CharField('接口名称', max_length=200, unique=True, help_text='接口名称')
    project = models.ForeignKey('projects.Projects', on_delete=models.CASCADE,
                                related_name='interfaces', help_text='所属项目')
    tester = models.CharField('测试人员', max_length=50, help_text='测试人员')
    desc = models.CharField('简要描述', max_length=200, null=True, blank=True, help_text='简要描述')

    class Meta:
        db_table = 'tb_interfaces'
        verbose_name = '接口信息'
        verbose_name_plural = verbose_name
        ordering = ('id',)

    def __str__(self):
        return self.name

这段代码定义了一个名为Testcases的Django模型类,继承了BaseModel。

首先,通过from django.db import models导入了Django的models模块和自定义的BaseModel模块。

然后,定义了Testcases模型类,它包含了以下字段:

  • id:主键字段,使用AutoField类型生成自增的id。
  • name:用例名称字段,使用CharField类型,最大长度为50,设置为唯一值。
  • interface:外键字段,关联到interfaces.Interfaces模型,表示该用例所属的接口。
  • include:前置字段,使用TextField类型,允许为空,保存用例执行前需要执行的顺序信息。
  • author:编写人员字段,使用CharField类型,最大长度为50,保存编写该用例的人员信息。
  • request:请求信息字段,使用TextField类型,保存请求的详细信息。

接下来,定义了该模型类的Meta类,包含了一些元数据:

  • db_table:数据库表的名称,设置为tb_testcases。
  • verbose_name:该模型的可读名称,设置为'用例信息'。
  • verbose_name_plural:该模型的复数形式名称,与verbose_name相同。
  • ordering:查询结果的默认排序规则,按照id字段进行升序排序。

最后,定义了__str__方法,返回用例的名称,用于在后台管理界面和其他地方显示该模型对象的可读信息。

通过以上定义,您可以使用Django框架创建一个名为Testcases的数据表,其中包含了上述定义的字段,并且可以进行数据操作和查询。

注意:

所有请求相关的信息,如header、URI、请求体、断言等等,全部在模型类 request字段中

request的值,是一个json字符串。如:

python 复制代码
{
	"test": {
		"name": "1陈帅百度",
		"request": {
			"url": "/mcp/pc/pcsearch",
			"method": "POST",
			"json": {
				"invoke_info": {
					"pos_1": [{}],
					"pos_2": [{}],
					"pos_3": [{}]
				}
			}
		},
		"validate": [{
			"check": "status_code",
			"expected": 200,
			"comparator": "equals"
		}]
	}
}

包含了请求与断言的信息。

底层使用的httprunner 1.0 做的接口自动化驱动,case的形式,就是json格式的。

相关资料:

httprunner 2.x的基本使用(二)_做测试的喵酱的博客-CSDN博客

三、序列化器类

python 复制代码
class TestcaseModelSerializer(serializers.ModelSerializer):
    interface = InterfaceProjectModelSerializer(label='所属项目和接口信息', help_text='所属项目和接口信息')

    class Meta:
        model = Testcases
        exclude = ('create_datetime', 'update_datetime')
        extra_kwargs = {
            'request': {
                'write_only': True
            },
            'include': {
                'write_only': True
            },
        }

    # def validate_request(self, attr):
    #     # TODO
    #     return attr
    #
    # def validate(self, attrs):
    #     # TODO
    #     return attrs

    def to_internal_value(self, data):
        result = super().to_internal_value(data)
        iid = data.get('interface').get('iid')
        result['interface'] = Interfaces.objects.get(id=iid)
        return result

    # def create(self, validated_data):
    #     pass


# class TestcaseRunSerializer(serializers.ModelSerializer):
#     env_id = serializers.IntegerField(label="所属环境id", help_text="所属环境id",
#                                       validators=[ManualValidateIsExist('env')])
#
#     class Meta:
#         model = Testcases
#         fields = ('id', 'env_id')

class TestcaseRunSerializer(RunSerializer):

    class Meta(RunSerializer.Meta):
        model = Testcases

四、视图

python 复制代码
import json
import os
from datetime import datetime

from django.conf import settings
from django.http import JsonResponse
from rest_framework import viewsets
from rest_framework import permissions
from rest_framework.response import Response
from rest_framework.decorators import action

from .models import Testcases
from envs.models import Envs
from . import serializers
from utils import handle_datas, common
from utils.mixins import RunMixin


class TestcasesViewSet(RunMixin, viewsets.ModelViewSet):

    queryset = Testcases.objects.all()
    serializer_class = serializers.TestcaseModelSerializer
    permission_classes = [permissions.IsAuthenticated]

    # 删除
    def destroy(self, request, *args, **kwargs):
        response = super().destroy(request, *args, **kwargs)
        response.status_code = 200
        response = {"code":2000,"msg":"删除成功"}
        response =JsonResponse(response)
        return response

    # 获取单个详情
    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object() # type: Testcases
        try:
            testcase_include = json.loads(instance.include, encoding='utf-8')
        except Exception:
            testcase_include = dict()

        try:
            testcase_request = json.loads(instance.request, encoding='utf-8')
        except Exception:
            return Response({'msg': '用例格式有误', 'status': 400}, status=400)

        testcase_request_data = testcase_request.get('test').get('request')
        # 获取json参数
        json_data = testcase_request_data.get('json')
        json_data_str = json.dumps(json_data, ensure_ascii=False)

        # 获取extract参数
        extract_data = testcase_request.get('test').get('extract')
        extract_data = handle_datas.handle_data3(extract_data)

        # 获取validate参数
        validate_data = testcase_request.get('test').get('validate')
        validate_data = handle_datas.handle_data1(validate_data)

        # 获取variables参数
        variables_data = testcase_request.get('test').get('variables')
        variables_data = handle_datas.handle_data2(variables_data)

        # 获取parameters参数
        parameters_data = testcase_request.get('test').get('parameters')
        parameters_data = handle_datas.handle_data3(parameters_data)

        # 获取setup_hooks参数
        setup_hooks_data = testcase_request.get('test').get('setup_hooks')
        setup_hooks_data = handle_datas.handle_data5(setup_hooks_data)

        # 获取teardown_hooks参数
        teardown_hooks_data = testcase_request.get('test').get('teardown_hooks')
        teardown_hooks_data = handle_datas.handle_data5(teardown_hooks_data)

        data = {
            "author": instance.author,
            "testcase_name": instance.name,
            "selected_configure_id": testcase_include.get('config'),
            "selected_interface_id": instance.interface_id,
            "selected_project_id": instance.interface.project_id,
            "selected_testcase_id": testcase_include.get('testcases', []),
            "method": testcase_request_data.get('method'),
            "url": testcase_request_data.get('url'),
            "param": handle_datas.handle_data4(testcase_request_data.get('params')),
            "header": handle_datas.handle_data4(testcase_request_data.get('headers')),
            "variable": handle_datas.handle_data2(testcase_request_data.get('data')),
            "jsonVariable": json_data_str,
            "extract": extract_data,
            "validate": validate_data,
            # 用例的当前配置(variables)
            "globalVar": variables_data,
            "parameterized": parameters_data,
            "setupHooks": setup_hooks_data,
            "teardownHooks":teardown_hooks_data
        }

        return Response(data, status=200)

    # @action(methods=['post'], detail=True)
    # def run(self, request, *args, **kwargs):
    #     # 1、取出用例模型对象并获取env_id
    #     # instance = self.get_object()    # type: Testcases
    #     # serializer = self.get_serializer(data=request.data)
    #     # serializer.is_valid(raise_exception=True)
    #     # env_id = serializer.validated_data.get('env_id')
    #     # env = Envs.objects.get(id=env_id)
    #
    #     # 2、创建以时间戳命名的目录
    #     # dirname = datetime.strftime(datetime.now(), "%Y%m%d%H%M%S")
    #     # testcase_dir_path = os.path.join(settings.PROJECT_DIR, datetime.strftime(datetime.now(), "%Y%m%d%H%M%S"))
    #     # os.makedirs(testcase_dir_path)
    #
    #     # 3、创建以项目名命名的目录
    #     # 4、生成debugtalks.py、yaml用例文件
    #     # common.generate_testcase_file(instance, env, testcase_dir_path)
    #
    #     # 5、运行用例并生成测试报告
    #     # return common.run_testcase(instance, testcase_dir_path)
    #     qs = [self.get_object()]
    #     return self.execute(qs)

    def get_serializer_class(self):
        if self.action == "run":
            return serializers.TestcaseRunSerializer
        else:
            return super().get_serializer_class()

    def get_testcase_qs(self):
        return [self.get_object()]
        # return self.queryset.filter(id=self.get_object().id)

这段代码是一个Django视图集,用于处理测试用例的增删改查操作。它继承了RunMixin类,并且使用了ModelViewSet视图集来简化代码。

该视图集定义了以下几个方法:

  1. destroy: 重写了父类的destroy方法,删除指定的测试用例,并返回一个删除成功的响应。
  2. retrieve: 重写了父类的retrieve方法,获取单个测试用例的详情,并将相关数据进行处理后返回。
  3. get_serializer_class: 根据请求的动作不同,选择不同的序列化器进行序列化。
  4. get_testcase_qs: 获取测试用例的查询集。

除此之外,还有一段被注释掉的代码,它包含了运行测试用例的逻辑,根据时间戳创建目录、生成测试用例文件,并运行测试用例生成测试报告。

需要注意的是,这段代码中使用了一些自定义的工具类和函数,如handle_datas、common等,未提供相关代码,可能需要根据实际情况自行补充。

相关推荐
jay神1 小时前
2026年YOLO还有哪些创新点可以做?
python·yolo·毕业设计·科研·课程设计·创新
傲笑风10 小时前
【openvino】tinybert基于openvino服务化部署(四)
人工智能·python·自然语言处理·nlp·bert·openvino
维基框架10 小时前
WIKI 知识库 v1.1.1 正式发布
人工智能·python
Mr数据杨12 小时前
【Codex】用下载中心模块管理系统导出文件与下载任务
django·codex·项目开发
谢白羽14 小时前
SGLang的AWQ量化笔记
笔记·python·sglang
迷迭香yy14 小时前
基金档案数据工程实战从收入分析到持仓穿透的Python解析 IG50免费开源股票数据API接口
开发语言·python
代码方舟14 小时前
零信任架构实战:基于天远车辆估值构建自动化二手车评估网关
运维·人工智能·架构·自动化
清水白石00814 小时前
Python 类型设计深度解析:TypedDict 能否替代 dataclass?从 JSON 数据边界到 API 设计的最佳实践
java·python·json
️学习的小王15 小时前
Git项目提交忽略文件怎么做?以Python项目为例,详解.gitignore
git·python·elasticsearch
前端 贾公子15 小时前
第09章:上下文与记忆 (6)
开发语言·前端·python