测试开发进阶(三十四)

数据库模型图

创建app

根据上面的数据库设计,创建9个app

  • configures

  • debugtalks

  • envs

  • interfaces

  • projects

  • reports

  • testsuits

  • testcases

  • user

完成注册

  1. import sys

  2. sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))

  3. INSTALLED_APPS = [

  4. 'django.contrib.admin',

  5. 'django.contrib.auth',

  6. 'django.contrib.contenttypes',

  7. 'django.contrib.sessions',

  8. 'django.contrib.messages',

  9. 'django.contrib.staticfiles',

  10. 'rest_framework',

  11. 'corsheaders',

  12. 'configures.apps.ConfiguresConfig',

  13. 'debugtalks.apps.DebugtalksConfig',

  14. 'envs.apps.EnvsConfig',

  15. 'interfaces.apps.InterfacesConfig',

  16. 'projects.apps.ProjectsConfig',

  17. 'reports.apps.ReportsConfig',

  18. 'testsuits.apps.TestsuitsConfig',

  19. 'testcases.apps.TestcasesConfig',

  20. 'user.apps.UserConfig',

  21. ]

抽象数据库基类

从数据库模型图可以看出,有很多部分都重复了

  • create_time

  • update_time

  • is_delete

  1. from django.db import models

  2. class BaseModel(models.Model):

  3. """

  4. 数据库表公共字段

  5. """

  6. create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间", help_text="创建时间")

  7. update_time = models.DateTimeField(auto_now=True, verbose_name="更新时间", help_text="更新时间")

  8. is_delete = models.BooleanField(default=False, verbose_name="逻辑删除", help_text="逻辑删除")

  9. class Meta:

  10. # 为抽象模型类, 用于其他模型来继承,数据库迁移时不会创建BaseModel表

  11. abstract = True

  12. verbose_name = "公共字段表"

  13. db_table = 'BaseModel'

default=False默认情况下不删除

各模块的模型

configures

  1. # configures.models.Configures

  2. from django.db import models

  3. from utils.base_models import BaseModel

  4. class Configures(BaseModel):

  5. id = models.AutoField(verbose_name='id主键', primary_key=True, help_text='id主键')

  6. name = models.CharField('配置名称', max_length=50, help_text='配置名称')

  7. interface = models.ForeignKey('interfaces.Interfaces',

  8. on_delete=models.CASCADE,

  9. related_name='configures',

  10. help_text='所属接口')

  11. author = models.CharField('编写人员', max_length=50, help_text='编写人员')

  12. request = models.TextField('请求信息', help_text='请求信息')

  13. class Meta:

  14. db_table = 'tb_configures'

  15. verbose_name = '配置信息'

  16. verbose_name_plural = verbose_name

  17. def __str__(self):

  18. return self.name

debugtalks

  1. # debugtalks.models.DebugTalks

  2. from django.db import models

  3. from utils.base_models import BaseModel

  4. class DebugTalks(BaseModel):

  5. id = models.AutoField(verbose_name='id主键', primary_key=True, help_text='id主键')

  6. name = models.CharField('debugtalk文件名称', max_length=200, default='debugtalk.py', help_text='debugtalk文件名称')

  7. debugtalk = models.TextField(null=True, default='#debugtalk.py', help_text='debugtalk.py文件')

  8. project = models.OneToOneField('projects.Projects', on_delete=models.CASCADE,

  9. related_name='debugtalks', help_text='所属项目')

  10. class Meta:

  11. db_table = 'tb_debugtalks'

  12. verbose_name = 'debugtalk.py文件'

  13. verbose_name_plural = verbose_name

  14. def __str__(self):

  15. return self.name

interfaces

  1. # interfaces.models.Interfaces

  2. from django.db import models

  3. from utils.base_models import BaseModel

  4. class Interfaces(BaseModel):

  5. id = models.AutoField(verbose_name='id主键', primary_key=True, help_text='id主键')

  6. name = models.CharField('接口名称', max_length=200, unique=True, help_text='接口名称')

  7. project = models.ForeignKey('projects.Projects', on_delete=models.CASCADE,

  8. related_name='interfaces', help_text='所属项目')

  9. tester = models.CharField('测试人员', max_length=50, help_text='测试人员')

  10. desc = models.CharField('简要描述', max_length=200, null=True, blank=True, help_text='简要描述')

  11. class Meta:

  12. db_table = 'tb_interfaces'

  13. verbose_name = '接口信息'

  14. verbose_name_plural = verbose_name

  15. def __str__(self):

  16. return self.name

projects

  1. # projects.models.Projects

  2. from django.db import models

  3. from utils.base_models import BaseModel

  4. class Projects(BaseModel):

  5. id = models.AutoField(verbose_name='id主键', primary_key=True, help_text='id主键')

  6. name = models.CharField('项目名称', max_length=200, unique=True, help_text='项目名称')

  7. leader = models.CharField('负责人', max_length=50, help_text='项目负责人')

  8. tester = models.CharField('测试人员', max_length=50, help_text='项目测试人员')

  9. programmer = models.CharField('开发人员', max_length=50, help_text='开发人员')

  10. publish_app = models.CharField('发布应用', max_length=100, help_text='发布应用')

  11. desc = models.CharField('简要描述', max_length=200, null=True, blank=True, default='', help_text='简要描述')

  12. class Meta:

  13. db_table = 'tb_projects'

  14. verbose_name = '项目信息'

  15. verbose_name_plural = verbose_name

  16. def __str__(self):

  17. return self.name

reports

  1. # reports.models.Reports

  2. from django.db import models

  3. from utils.base_models import BaseModel

  4. class Reports(BaseModel):

  5. id = models.AutoField(verbose_name='id主键', primary_key=True, help_text='id主键')

  6. name = models.CharField('报告名称', max_length=200, unique=True, help_text='报告名称')

  7. result = models.BooleanField('执行结果', default=1, help_text='执行结果') # 1为成功, 0为失败

  8. count = models.IntegerField('用例总数', help_text='总用例数')

  9. success = models.IntegerField('成功总数', help_text='成功总数')

  10. html = models.TextField('报告HTML源码', help_text='报告HTML源码', null=True, blank=True, default='')

  11. summary = models.TextField('报告详情', help_text='报告详情', null=True, blank=True, default='')

  12. class Meta:

  13. db_table = 'tb_reports'

  14. verbose_name = '测试报告'

  15. verbose_name_plural = verbose_name

  16. def __str__(self):

  17. return self.name

testcases

  1. # testcases.models.Testcases

  2. from django.db import models

  3. from utils.base_models import BaseModel

  4. class Testcases(BaseModel):

  5. id = models.AutoField(verbose_name='id主键', primary_key=True, help_text='id主键')

  6. name = models.CharField('用例名称', max_length=50, unique=True, help_text='用例名称')

  7. interface = models.ForeignKey('interfaces.Interfaces', on_delete=models.CASCADE,

  8. help_text='所属接口')

  9. # include = models.ForeignKey('', on_delete=models.SET_NULL, null=True, related_name='testcases')

  10. include = models.TextField('前置', null=True, help_text='用例执行前置顺序')

  11. author = models.CharField('编写人员', max_length=50, help_text='编写人员')

  12. request = models.TextField('请求信息', help_text='请求信息')

  13. class Meta:

  14. db_table = 'tb_testcases'

  15. verbose_name = '用例信息'

  16. verbose_name_plural = verbose_name

  17. def __str__(self):

  18. return self.name

testsuits

  1. # testsuits.models.Testsuits

  2. from django.db import models

  3. from utils.base_models import BaseModel

  4. class Testsuits(BaseModel):

  5. id = models.AutoField(verbose_name='id主键', primary_key=True, help_text='id主键')

  6. name = models.CharField('套件名称', max_length=200, unique=True, help_text='套件名称')

  7. project = models.ForeignKey('projects.Projects', on_delete=models.CASCADE,

  8. related_name='testsuits', help_text='所属项目')

  9. # include = models.TextField(null=False)

  10. include = models.TextField('包含的接口', null=False, help_text='包含的接口')

  11. class Meta:

  12. db_table = 'tb_testsuits'

  13. verbose_name = '套件信息'

  14. verbose_name_plural = verbose_name

  15. def __str__(self):

  16. return self.name

projects需求

  • 删除项目时,只进行逻辑删除

  • 获取项目列表信息时,要求能获取此项目下的「接口总数」,「用例总数」,「配置总数」,「套件总数」,同时输出创建时间,格式为2019-11-05 11:43:00

  • 要求提供获取此项目下的所有项目名的接口

  • 要求提供获取此项目下的所有接口信息的接口

序列化器

  1. from rest_framework import serializers

  2. from .models import Projects

  3. from debugtalks.models import DebugTalks

  4. from interfaces.models import Interfaces

  5. class ProjectModelSerializer(serializers.ModelSerializer):

  6. class Meta:

  7. model = Projects

  8. exclude = ('update_time', 'is_delete')

  9. extra_kwargs = {

  10. 'create_time': {

  11. 'read_only': True

  12. }

  13. }

  14. def create(self, validated_data):

  15. project_obj = super().create(validated_data)

  16. DebugTalks.objects.create(project=project_obj)

  17. return project_obj

  18. class ProjectNameSerializer(serializers.ModelSerializer):

  19. class Meta:

  20. model = Projects

  21. fields = ('id', 'name')

  22. class InterfaceNameSerializer(serializers.ModelSerializer):

  23. class Meta:

  24. model = Interfaces

  25. fields = ('id', 'name', 'tester')

  26. class InterfacesByProjectIdSerializer(serializers.ModelSerializer):

  27. interfaces_set = InterfaceNameSerializer(read_only=True, many=True)

  28. class Meta:

  29. model = Projects

  30. fields = ('id', 'interfaces_set')

视图

继承 ModelViewSet

  1. from rest_framework.viewsets import ModelViewSet

  2. from rest_framework import permissions

  3. from rest_framework.decorators import action

  4. from rest_framework.response import Response

  5. from rest_framework.exceptions import NotFound

  6. from . import serializer

  7. from .models import Projects

  8. from .utils import get_count_by_project

  9. from interfaces.models import Interfaces

  10. class ProjectsViewSet(ModelViewSet):

  11. """

  12. list:

  13. 返回项目(多个)列表数据

  14. create:

  15. 创建项目

  16. retrieve:

  17. 返回项目(单个)详情数据

  18. update:

  19. 更新(全)项目

  20. partial_update:

  21. 更新(部分)项目

  22. destroy:

  23. 删除项目

  24. names:

  25. 返回所有项目ID和名称

  26. interfaces:

  27. 返回某个项目的所有接口信息(ID和名称)

  28. """

  29. queryset = Projects.objects.filter(is_delete=False)

  30. serializer_class = serializer.ProjectModelSerializer

  31. permission_classes = (permissions.IsAuthenticated,)

  32. ordering_fields = ('id', 'name')

  33. def perform_destroy(self, instance):

  34. instance.is_delete = True

  35. instance.save() # 逻辑删除

  36. @action(methods=['get'], detail=False)

  37. def names(self, request, *args, **kwargs):

  38. queryset = self.get_queryset()

  39. serializer = serializer.ProjectNameSerializer(instance=queryset, many=True)

  40. return Response(serializer.data)

  41. @action(methods=['get'], detail=True)

  42. def interfaces(self, request, pk=None):

  43. interface_objs = Interfaces.objects.filter(project_id=pk, is_delete=False)

  44. one_list = []

  45. for obj in interface_objs:

  46. one_list.append({

  47. 'id': obj.id,

  48. 'name': obj.name

  49. })

  50. return Response(data=one_list)

  51. def list(self, request, *args, **kwargs):

  52. queryset = self.filter_queryset(self.get_queryset())

  53. page = self.paginate_queryset(queryset)

  54. if page is not None:

  55. serializer = self.get_serializer(page, many=True)

  56. datas = serializer.data

  57. datas = get_count_by_project(datas)

  58. return self.get_paginated_response(datas)

  59. serializer = self.get_serializer(queryset, many=True)

  60. datas = serializer.data

  61. datas = get_count_by_project(datas)

  62. return Response(datas)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章