Django implements interface automation platform (14) test case module Testcases serializer and view [continuously updated]

related articles:

Django implements interface automation platform (thirteen) interface module Interfaces serializer and view [continuously updated]_Do test meow sauce blog-CSDN blog

This chapter is a breakdown of the project. When viewing the content of this chapter, it should be viewed in conjunction with the overall project code:

Python django vue httprunner implements interface automation platform (final version)

1. Testcases application and related interfaces

request method URI corresponding action Realize function
GET /testcases/ .list() Query testcase list
POST /testcases/ .create() Create a piece of data
GET /testcases/{id}/ .retrieve() Retrieve detailed data of a testcase
PUT /testcases/{id}/ update() Update all fields in a piece of data
PATCH /testcases/{id}/ .partial_update() Update some fields in a piece of data
DELETE /testcases/{id}/ .destroy() delete a piece of data
POST /testcases/{id}/run/ Run all cases under a certain interface

 1.1 List of use cases

GET /testcases/ .list() Query testcase list

1.2 Create use cases 

1.2.1 Basic Information

 1. Pulled the project list

2. Pulled the interface list under the project

3. List of pre-use cases

4. Pulled all configuration lists

1.2.2 Basic Information

 

 

2. Model class

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

This code defines a Django model class called Testcases that extends BaseModel.

First, the Django models module and the custom BaseModel module are imported through from django.db import models.

Then, the Testcases model class is defined, which contains the following fields:

  • id: primary key field, use the AutoField type to generate an auto-incremented id.
  • name: Use case name field, using CharField type, the maximum length is 50, set as a unique value.
  • interface: foreign key field, associated with the interfaces.Interfaces model, indicating the interface to which the use case belongs.
  • include: pre-field, using the TextField type, which is allowed to be empty, and saves the sequence information that needs to be executed before the use case is executed.
  • author: author field, use CharField type, the maximum length is 50, save the author information of this use case.
  • request: The request information field, using the TextField type, saves the detailed information of the request.

Next, the Meta class of the model class is defined, which contains some metadata:

  • db_table: The name of the database table, set to tb_testcases.
  • verbose_name: A human-readable name for the model, set to 'use case info'.
  • verbose_name_plural: The plural form name of the model, same as verbose_name.
  • ordering: The default sorting rules for query results, sorted in ascending order according to the id field.

Finally, the __str__ method is defined, which returns the name of the use case, which is used to display the readable information of the model object in the background management interface and other places.

Through the above definitions, you can use the Django framework to create a data table named Testcases, which contains the fields defined above, and can perform data operations and queries.

Notice:

All request-related information, such as header, URI, request body, assertion, etc., are all in the  request field of the model class .

The value of request is a json string. like:

{
	"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"
		}]
	}
}

Contains information about requests and assertions.

The interface automation driver made by httprunner 1.0 used at the bottom layer is in json format.

Relevant information:

Basic use of httprunner 2.x (2)

3. Serializer class


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

4. View 

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)

 

This code is a Django view set, which is used to handle the addition, deletion, modification and query of test cases. It extends the RunMixin class and uses the ModelViewSet view set to simplify the code.

This viewset defines the following methods:

  1. destroy: Override the destroy method of the parent class, delete the specified test case, and return a successful deletion response.
  2. retrieve: Override the retrieve method of the parent class to obtain the details of a single test case, and return the relevant data after processing.
  3. get_serializer_class: Select different serializers for serialization according to different requested actions.
  4. get_testcase_qs: Get the queryset of test cases.

In addition, there is a piece of code that is commented out, which contains the logic of running the test case, creating a directory according to the timestamp, generating the test case file, and running the test case to generate a test report.

It should be noted that some custom tool classes and functions are used in this code, such as handle_datas, common, etc. The relevant codes are not provided and may need to be supplemented according to the actual situation.

Guess you like

Origin blog.csdn.net/qq_39208536/article/details/131789464