一、 测试步骤创建
接口名称: /test_steps/
请求方式: POST
参数格式: JSON
请求参数:
参数 | 变量名 | 类型 | 说明 | 是否必传 |
用例名称 | name | 字符串 | 任务名称 | 是 |
接口id | interface | 整数 | 所属项目id | 是 |
请求头 | headers | json | 包含模块的id数组 | 否 |
请求参数 | request | json | 请求体参数 | 否 |
上传文件参数 | file | json | 上传文件参数 | 否 |
前置脚本 | setup_script | 字符串 | 前置执行脚本 | 否 |
后置脚本 | teardown_script | 字符串 | 后置执行脚本 | 否 |
请求示例:
json格式参数
{
"title": "登录成功",
"headers": {},
"request": {},
"file": [],
"setup_script": "# 前置脚本(python):\n# global_tools:全局工具函数\n# data:用例数据
\n# env: 局部环境\n# ENV: 全局环境\n# db: 数据库操作对象\n",
"teardown_script": "# 后置脚本(python):\n# global_tools:全局工具函数\n# data:用例数据
\n# response:响应对象response \n# env: 局部环境\n# ENV: 全局环境\n# db: 数据库操作对象\n",
"interface": 1
}
返回示例
响应状态码:201
响应数据:
{
"id": 1,
"title": "登录成功",
"headers": {},
"request": {},
"file": [],
"setup_script": "# 前置脚本(python):\n# global_tools:全局工具函数\n# data:用例数据
\n# env: 局部环境\n# ENV: 全局环境\n# db: 数据库操作对象\n",
"teardown_script": "# 后置脚本(python):\n# global_tools:全局工具函数\n# data:用例数据 \n# response:响应对象response \n# env: 局部环境\n# ENV: 全局环境\n# db: 数据库操作对象\n",
"interface": 1
}
二、 删除测试步骤
接口名称: /test_steps/id/
请求方式: DELETE
参数格式: 路径参数
请求参数: 无
返回示例
响应状态码:204
响应数据:无
三、修改测试步骤
接口名称: /test_steps/id/
请求方式: PUT/PATCH
参数格式: JSON
请求参数:
参数 | 变量名 | 类型 | 说明 | 是否必传 |
用例名称 | name | 字符串 | 任务名称 | put请求必传 |
接口id | interface | 整数 | 所属项目id | put请求必传 |
请求头 | headers | json | 包含模块的id数组 | 否 |
请求参数 | request | json | 请求体参数 | 否 |
上传文件参数 | file | json | 上传文件参数 | 否 |
前置脚本 | setup_script | 字符串 | 前置执行脚本 | 否 |
后置脚本 | teardown_script | 字符串 | 后置执行脚本 | 否 |
请求示例:
json格式参数
{
"title": "登录成功",
"headers": {},
"request": {},
"file": [],
"setup_script": "# 前置脚本(python):\n# global_tools:全局工具函数\n# data:用例数据
\n# env: 局部环境\n# ENV: 全局环境\n# db: 数据库操作对象\n",
"teardown_script": "# 后置脚本(python):\n# global_tools:全局工具函数\n# data:用例数据
\n# response:响应对象response \n# env: 局部环境\n# ENV: 全局环境\n# db: 数据库操作对象\n",
"interface": 1
}
返回示例
响应状态码:200 响应数据:
{
"id": 1,
"title": "登录成功",
"headers": {},
"request": {},
"file": [],
"setup_script": "# 前置脚本(python):\n# global_tools:全局工具函数\n# data:用例数据
\n# env: 局部环境\n# ENV: 全局环境\n# db: 数据库操作对象\n",
"teardown_script": "# 后置脚本(python):\n# global_tools:全局工具函数\n# data:用例数据 \n# response:响应对象response \n# env: 局部环境\n# ENV: 全局环境\n# db: 数据库操作对象\n",
"interface": 1
}
四、查看测试步骤列表
接口名称: /test_steps/
请求方式: GET
参数格式:
无请求参数:
参数 | 变量名 | 类型 | 说明 | 是否必传 |
测试场景 | scene | 整数 | 测试场景id | 否 |
接口 | interface | 整数 | 接口id | 否 |
返回示例
响应状态码:200
响应数据:
[
{
"id": 1,
"title": "登录成功",
"headers": {},
"request": {},
"file": [],
"setup_script": "# 前置脚本(python):\n# global_tools:全局工具函数\n# data:用例数据 \n# env: 局部环境\n# ENV: 全局环境\n# db: 数据库操作对象\n",
"teardown_script": "# 后置脚本(python):\n# global_tools:全局工具函数\n# data:用例数据 \n# response:响应对象response \n# env: 局部环境\n# ENV: 全局环境\n# db: 数据库操作对象\n",
"interface": 1
}
]
五、查看测试步骤
接口名称: /test_steps/id/
请求方式: GET
参数格式: 路径参数
请求参数: 无
返回示例
响应状态码:200
响应数据:
{
"id": 1,
"interface": {
"id": 1,
"steps": [{
"id": 1,
"title": "登录成功"
}],
"name": "登录",
"url": "/users/login/",
"method": "POST",
"type": "1",
"project": 1
},
"title": "登录成功",
"headers": {},
"request": {},
"file": [],
"setup_script": "# 前置脚本(python):\n# global_tools:全局工具函数\n# data:用例数据\n# env: 局部环境\n# ENV: 全局环境\n# db: 数据库操作对象\n",
"teardown_script": "# 后置脚本(python):\n# global_tools:全局工具函数\n# data:用例数据 \n# response:响应对象response \n# env: 局部环境\n# ENV: 全局环境\n# db: 数据库操作对象\n"
}
六、 后端代码
1. 序列化器
在testcases应用中创建serializers.py 模块,编写代码如下:
from projects.serializers import InterfaceSerializer
from .models import TestStep, UploadFile, TestScene, SceneData
from rest_framework.serializers import ModelSerializer
class TestStepSerializer(ModelSerializer):
"""测试步骤序列化器"""
class Meta:
model = TestStep
fields = ' all '
class TestStepRetrieveSerializer(ModelSerializer):
"""测试步骤详情序列化器"""
interface = InterfaceSerializer()
class Meta:
model = TestStep
fields = ' all '
测试步骤详情中需要展示接口信息,所以单独创建一个序列化器用来序列化测试步骤详情。
或者直接在测试步骤序列化器中加个depth =1。但是这样子会把新建测试用例选择接口的时候,接口这个字段没有了,因为变成只读的了。
2. 过滤器
可以直接在filterset_fields = ['interface']通过接口去过滤,那怎么通过测试场景去过滤呢?直接在filterset_fields加个可以吗,显示是不行的,因为TestStep模型中压根就没有这个字段。
那该怎么办? TestStep模型和TestScene模型(测试用例和测试场景是多对多),我们可以通过中间表SceneData去查询。
比如说我想查scene_id=1的这个场景下所有的测试用例,那这个我们该怎么写呢?
我们先进入shell
In [4]: from testplans.models import *
In [5]: queryset = TestStep.objects.filter(scenedata__scene=1)
In [6]: print(queryset)
<QuerySet []>
In [7]: print(queryset.query)
SELECT `tb_test_step`.`id`, `tb_test_step`.`title`, `tb_test_step`.`interface_id`, `tb_test_step`.`headers`, `tb_test_step`.`request`, `tb_test_step`.`file`, `tb_test_step`.`setup_script`, `tb_test_step`.`teardown_script` FROM `tb_test_step` INNER JOIN `tb_scene_data` ON (`tb_test_step`.`id` = `tb_scene_data`.`step_id`) WHERE `tb_scene_data`.`scene_id` = 1
In [8]:
所以如果我这样子配也是可以的,但是不美观,我们还可以有其他的办法。
那就是复写过滤器。
在testplans/filters.py 中定义如下过滤器:
from .models import TestStep
from django_filters import rest_framework as filters
class StepFilterSet(filters.FilterSet):
"""测试步骤过滤器"""
scene = filters.NumberFilter(field_name='scenedata scene')
class Meta:
model = TestStep
fields = ['scene', 'interface']
然后在视图里添加 filterset_class = TestStepFilter
3. 视图
复写 get_serializer_class方法,实现不同的操作使用不同的序列化器 。
我们看下父类的 get_serializer_class方法,也是直接返回一个序列化器对象。
self.action是啥?当我们是查询数据集的时候,action就是list;当我们是创建的时候,action就是create;当我们是修改数据的时候,action就是update或者是partial_update;当我们删除的时候,他就是destroy。当我们去查看某一个的数据的时候,那他就是retrieve。
所以我们可以根据action这个属性是什么去返回不同的序列化器。
class TestStepViewSet(ModelViewSet):
"""测试步骤视图集"""
queryset = TestStep.objects.all()
serializer_class = TestStepSerializer
permission_classes = [IsAuthenticated]
filterset_class = StepFilterSet
# 方法1
def get_serializer_class(self):
if self.action == 'retrieve':
return TestStepRetrieveSerializer
return super().get_serializer_class()
# 方法二
def get_serializer_class(self):
if self.action == 'retrieve':
return TestStepRetrieveSerializer
return self.serializer_class
4. 路由
from rest_framework.routers import DefaultRouter
from . import views
route = DefaultRouter()
route.register('test_steps', views.TestStepViewSet)
urlpatterns = route.urls