測試開發進階(三十四)

數據庫模型圖

創建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)

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