related articles:
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:
- destroy: Override the destroy method of the parent class, delete the specified test case, and return a successful deletion response.
- 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.
- get_serializer_class: Select different serializers for serialization according to different requested actions.
- 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.