软件工程第二次结对作业

这个作业属于哪个课程 https://edu.cnblogs.com/campus/fzu/SE2024/
这个作业要求在哪里 https://edu.cnblogs.com/campus/fzu/SE2024/homework/13281
学号 102202117
组员 102202134承宇豪、102202117杨邑豪

1.具体分工

承宇豪(学号:102202134):负责前端 APP 页面以及底层代码设计。前端职责包括:

​ 1.设计和实现用户界面,确保页面布局美观、用户体验流畅

​ 2.处理用户交互逻辑,使用 Vue.js、HTML、CSS、JavaScript 等技术完成应用页面的开发。

​ 3.与后端进行 API 的集成,确保前后端数据通信顺畅,并对出现的前端问题进行调试和优化。

​ 4.对底层代码的设计和编写,确保代码结构合理,具有良好的可维护性和可扩展性。

杨邑豪(学号:102202117):负责后端功能实现。后端职责包括:

​ 1.设计和实现系统的业务逻辑,确保功能稳定可靠地运行。

​ 2.使用 Django 框架负责服务器端的开发,编写并维护 RESTful API

​ 3.处理数据库的交互,确保前端所需数据的获取、更新、创建和删除操作正确无误。

​ 4.对于用户身份验证、权限管理、安全性保障等功能模块进行开发,并优化后端代码以确保高性能。

​ 5.数据库的设计和维护,包括数据模型的定义、数据表的建立和数据库的优化,确保数据的完整性和一致性。

2.PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 20 20
Estimate 估计这个任务需要多少时间 60 60
Development 开发 2160 3780
Analysis 需求分析 (包括学习新技术) 200 140
Design Spec 生成设计文档 160 120
Design Review 设计复审 60 50
Coding Standard 代码规范 (为目前的开发制定合适的规范) 70 60
Design 具体设计 300 120
Coding 具体编码 1000 720
Code Review 代码复审 60 60
Test 测试(自我测试,修改代码,提交修改) 90 70
Reporting 报告 160 120
Test Repor 测试报告 0 0
Size Measurement 计算工作量 20 10
Postmortem&Process Improvement Plan 事后总结, 并提出过程改进计划 30 15
合计 4390 5346

3.解题思路与设计实现说明

3.1代码实现思路,文字描述

为了实现一个前后端分离的项目管理应用,前后端的设计思路可以分为如下几部分:

前端设计思路:

  1. 框架与工具选择

    • 使用 Vue.js 来构建单页应用(SPA),这些框架能够很好地支持组件化开发和高效的状态管理。
    • 对于表单验证和状态管理,使用或 Vuex(Vue)。
    • 使用 Axios 进行 API 请求管理,以方便与后端进行数据交互。
  2. 主要功能模块

    • 用户登录与注册:创建独立的登录和注册页面,表单提交时通过 API 调用后端接口进行身份验证。
      • 提供错误提示和验证规则(如密码强度、用户名重复等)。
      • 利用 JWT (JSON Web Token) 来进行会话管理。
    • 项目管理模块
      • 项目创建:提供表单页面允许用户输入项目信息,提交后发送到后端进行存储。
      • 项目展示:使用 REST API 获取用户的项目列表,并以卡片或表格形式展示。
      • 项目详情:当用户点击某个项目时,展示该项目的详细信息,并允许进行编辑和删除。
    • 用户权限与角色管理
      • 针对不同权限的用户,展示不同的功能页面(如管理员可以管理所有项目,普通用户只能管理自己的项目)。
  3. 路由与导航

    • 使用Vue Router 进行页面路由管理,确保不同的功能模块有独立的路径。
    • 实现基于用户登录状态的路由守卫,未登录的用户无法访问项目管理相关页面。
  4. UI 设计

    • 使用 Ant DesignMaterial UIElement UI 等 UI 库,加快开发速度并提升用户体验。
    • 响应式设计,确保应用在不同设备上都能友好展示。

后端设计思路:

  1. 框架与技术栈
    • 使用 Django (Python)后端框架,支持 RESTful API 的设计。
    • 数据库可以选择 MySQLPostgreSQLMongoDB 来存储用户、项目等信息。
    • 使用 JWTSession 来管理用户的登录状态。
  2. 数据库设计
    • 用户表 (User)
      • 字段:用户名、密码。
    • 项目表 (Project)
      • 字段:项目名称、团队组成、最高人数、团队情况、项目描述、项目图片。
  3. API 设计
    • 用户注册与登录 API
      • POST /api/register/:用户注册接口。
      • POST /api/login/:用户登录接口,成功后返回 JWT 或设置 Session。
    • 项目管理 API
      • GET /api/projects/:获取当前用户的所有项目。
      • POST /api/projects/:创建新项目。
      • GET /api/projects/:id/:获取指定项目的详细信息。
      • PUT /api/projects/:id/:更新项目信息。
      • DELETE /api/projects/:id/:删除项目。
    • 任务管理 API(可选):
      • 类似于项目管理的 API,增加任务的增删改查功能。
  4. 安全与权限管理
    • 通过中间件验证用户的身份,例如在每个需要用户登录的 API 请求前检查 JWT 或 Session 的有效性。
    • 使用角色或权限系统确保只有管理员可以删除其他用户的项目或管理用户信息。
  5. 部署与扩展
    • 使用 Docker 构建容器化应用,方便部署和维护。
    • 部署时使用 贝瑞花生壳 作为前端和后端的反向代理,将前端应用和后端 API 服务分别托管。

前后端交互流程:

  1. 用户在前端注册或登录,前端通过 API 调用后端接口,后端返回会话信息。
  2. 前端将用户以及项目信息保存在后端的数据库中。
  3. 用户在前端创建或管理项目时,通过 REST API 调用后端接口,后端根据用户身份进行项目数据的存储和管理。

3.2关键实现的流程图

3.3重要的/有价值的代码片段以及解释

3.3.1后端部分

from django.shortcuts import render
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt

# Create your views here.
from myapp.models import *
from myapp.models import book

@csrf_exempt
def add_user(request):
    try:
        # 创建模型类实例
        addUser = book()  # 根据实际模型修改
        # 从请求中获取数据
        username = request.POST.get('username')
        password = request.POST.get('password')
        addUser = book(username=username,password=password)


        # 调用 save 方法,保存数据到数据库
        addUser.save()

        # 返回成功的 JSON 响应
        return JsonResponse({
            'status': 'success',
            'message': 'User added successfully.',
            'user_id': addUser.id
        })
    except Exception as e:
        # 捕获异常并返回错误信息
        return JsonResponse({
            'status': 'error',
            'message': str(e)
        })# 调用save方法,保存数据到数据库

def get_user(request):
    # 获取所有书籍数据
    books = book.objects.all().values()

    # 返回 JSON 响应
    return JsonResponse(list(books), safe=False)


def find_user(request):
    # 从请求中获取查询参数
    username = request.GET.get('username')

    if not username:
        return JsonResponse({
            'status': 'error',
            'message': 'Username is required.'
        })

    try:
        # 查询数据库中是否存在该用户
        user = book.objects.filter(username=username).values('username', 'password')  # 确保返回密码字段

        if user.exists():
            # 返回找到的用户信息
            return JsonResponse({
                'status': 'success',
                'data': list(user)  # 将 QuerySet 转换为列表
            })
        else:
            # 用户不存在
            return JsonResponse({
                'status': 'not_found',
                'message': 'User not found.'
            })
    except Exception as e:
        # 捕获异常并返回错误信息
        return JsonResponse({
            'status': 'error',
            'message': str(e)
        })

@csrf_exempt
def delete_user(request):
    try:
        # 获取请求中的用户名
        username = request.POST.get('username')

        # 检查用户名是否为空
        if not username:
            return JsonResponse({
                'status': 'error',
                'message': 'Username is required.'
            })

        # 查找用户
        try:
            user = book.objects.get(username=username)
        except book.DoesNotExist:
            return JsonResponse({
                'status': 'error',
                'message': 'User not found.'
            })

        # 删除用户
        user.delete()

        # 返回成功响应
        return JsonResponse({
            'status': 'success',
            'message': f'User {username} deleted successfully.'
        })
    except Exception as e:
        # 捕获异常并返回错误信息
        return JsonResponse({
            'status': 'error',
            'message': str(e)
        })

@csrf_exempt
def update_user_password(request):
    try:
        # 从请求中获取数据
        username = request.POST.get('username')
        newPassword = request.POST.get('password')

        # 检查数据是否为空
        if not username or not newPassword:
            return JsonResponse({
                'status': 'error',
                'message': 'Username and new password are required.'
            })

        # 查找用户
        try:
            user = book.objects.get(username=username)
        except book.DoesNotExist:
            return JsonResponse({
                'status': 'error',
                'message': 'User not found.'
            })

        # 更新用户的密码
        user.password = newPassword
        user.save()

        # 返回成功的 JSON 响应
        return JsonResponse({
            'status': 'success',
            'message': f'Password for user {username} updated successfully.'
        })
    except Exception as e:
        # 捕获异常并返回错误信息
        return JsonResponse({
            'status': 'error',
            'message': str(e)
        })

@csrf_exempt
def add_project(request):
    try:
        # 从请求中获取数据
        projectname = request.POST.get('projectname')
        projectteam = request.POST.get('projectteam')
        projectpeople = request.POST.get('projectpeople')
        companysituation = request.POST.get('companysituation')
        projectdescription = request.POST.get('projectdescription')
        projectimage = request.FILES.get('image')  # 获取上传的文件

        # 检查必填字段是否为空
        if not projectname or not projectteam or not projectpeople:
            return JsonResponse({
                'status': 'error',
                'message': 'Project name, team, and people are required.'
            })

        # 创建新的项目实例并保存到数据库
        project = Project(
            projectname=projectname,
            projectteam=projectteam,
            projectpeople=int(projectpeople),
            companysituation=companysituation,
            projectdescription=projectdescription,
            image=projectimage  # 将图片赋值给项目
        )
        project.save()

        # 返回成功的 JSON 响应
        return JsonResponse({
            'status': 'success',
            'message': 'Project added successfully.',
            'project_id': project.id
        })
    except Exception as e:
        # 捕获异常并返回错误信息
        return JsonResponse({
            'status': 'error',
            'message': str(e)
        })


@csrf_exempt
def delete_project(request):
    try:
        # 从请求中获取项目名称
        projectname = request.POST.get('projectname')

        # 检查项目名称是否为空
        if not projectname:
            return JsonResponse({
                'status': 'error',
                'message': 'Project name is required.'
            })

        # 查找并删除项目
        try:
            project = Project.objects.get(projectname=projectname)
            project.delete()
            return JsonResponse({
                'status': 'success',
                'message': f'Project "{projectname}" deleted successfully.'
            })
        except Project.DoesNotExist:
            return JsonResponse({
                'status': 'error',
                'message': 'Project not found.'
            })
    except Exception as e:
        # 捕获异常并返回错误信息
        return JsonResponse({
            'status': 'error',
            'message': str(e)
        })

@csrf_exempt
def update_project(request):
    try:
        # 从请求中获取项目名称
        projectname = request.POST.get('projectname')

        # 检查项目名称是否为空
        if not projectname:
            return JsonResponse({
                'status': 'error',
                'message': 'Project name is required.'
            })

        # 查找项目
        try:
            project = Project.objects.get(projectname=projectname)
        except Project.DoesNotExist:
            return JsonResponse({
                'status': 'error',
                'message': 'Project not found.'
            })

        # 获取新的项目信息
        new_projectteam = request.POST.get('projectteam')
        new_projectpeople = request.POST.get('projectpeople')
        new_companysituation = request.POST.get('companysituation')
        new_projectdescription = request.POST.get('projectdescription')

        # 更新项目信息
        if new_projectteam:
            project.projectteam = new_projectteam
        if new_projectpeople:
            project.projectpeople = int(new_projectpeople)
        if new_companysituation:
            project.companysituation = new_companysituation
        if new_projectdescription:
            project.projectdescription = new_projectdescription

        # 保存更改
        project.save()

        # 返回成功的 JSON 响应
        return JsonResponse({
            'status': 'success',
            'message': f'Project "{projectname}" updated successfully.'
        })
    except Exception as e:
        # 捕获异常并返回错误信息
        return JsonResponse({
            'status': 'error',
            'message': str(e)
        })

# 视图函数,用于列出所有项目
def list_projects(request, sort_by='projectname'):
    # 根据排序参数选择排序字段
    if sort_by == 'projectteam':
        projects = Project.objects.order_by('projectteam')
    else:
        projects = Project.objects.order_by('projectname')

    # 构建项目列表的 JSON 数据
    projects_list = list(projects.values())

    return JsonResponse({'projects': projects_list})

解释:

这段代码包含一组基于 Django 框架的视图函数,用于实现用户和项目的基本增删改查(CRUD)功能。每个函数主要涉及处理用户或项目的数据,通过接收 HTTP 请求,处理数据,并返回 JSON 响应。

1. add_user 函数

  • 功能:添加用户。
  • 步骤:
    1. 从请求中获取用户名和密码。
    2. 使用这些信息创建一个 book 实例(这里 book 应该是一个用户模型,但名字有误导性)。
    3. 调用 .save() 方法将用户信息保存到数据库中。
    4. 返回一个包含状态和新用户 ID 的 JSON 响应。
    5. 如果发生错误,返回错误信息。

2. get_user 函数

  • 功能:获取所有用户信息。
  • 步骤:
    1. 使用 book.objects.all() 获取所有用户信息。
    2. 将用户信息转换为列表,并返回 JSON 响应。

3. find_user 函数

  • 功能:根据用户名查找用户。
  • 步骤:
    1. 从请求中获取用户名。
    2. 如果用户名为空,返回错误信息。
    3. 查询数据库是否存在该用户。
    4. 如果用户存在,返回用户信息,否则返回用户未找到的提示。

4. delete_user 函数

  • 功能:删除指定用户名的用户。
  • 步骤:
    1. 从请求中获取用户名。
    2. 检查用户名是否为空。
    3. 查找用户,如果用户存在则删除,否则返回用户未找到的提示。
    4. 返回删除成功或错误的响应。

5. update_user_password 函数

  • 功能:更新用户的密码。
  • 步骤:
    1. 从请求中获取用户名和新密码。
    2. 检查用户名和新密码是否为空。
    3. 查找用户,如果找到则更新密码。
    4. 返回更新成功或错误的响应。

6. add_project 函数

  • 功能:添加新项目。
  • 步骤:
    1. 从请求中获取项目信息(项目名称、团队、人员等)。
    2. 检查必填字段是否为空。
    3. 使用这些信息创建一个 Project 实例。
    4. 保存项目并返回成功的 JSON 响应。
    5. 如果发生错误,返回错误信息。

7. delete_project 函数

  • 功能:删除项目。
  • 步骤:
    1. 从请求中获取项目名称。
    2. 检查项目名称是否为空。
    3. 查找项目,如果找到则删除,否则返回项目未找到的提示。
    4. 返回删除成功或错误的响应。

8. update_project 函数

  • 功能:更新项目的信息。
  • 步骤:
    1. 从请求中获取项目名称。
    2. 检查项目名称是否为空。
    3. 查找项目,如果找到则更新其信息。
    4. 保存更改并返回成功的响应。
    5. 如果发生错误,返回错误信息。

9. list_projects 函数

  • 功能:列出所有项目。
  • 步骤:
    1. 根据请求中的排序参数来选择按 projectnameprojectteam 排序。
    2. 获取并返回所有项目的列表作为 JSON 响应。

3.3.2前端部分

loadProjects() {
  uni.request({
    url: 'http://ci86ph16222.vicp.fun/listProjects/?sort_by=projectname', // 使用您的后端 API 地址
    method: 'GET',
    success: (res) => {
      if (res.statusCode === 200) {
        const data = res.data;
        if (data.projects && Array.isArray(data.projects)) {
          this.$set(this, 'projects', data.projects);
          this.$set(this, 'filteredProjects', data.projects);
        } else {
          console.error('返回的数据格式不正确:', data);
          uni.showToast({ title: '数据格式错误,请检查后端返回的数据结构', icon: 'none' });
        }
      } else {
        console.error(`请求失败,状态码: ${res.statusCode}`, res.data);
        uni.showToast({ title: `请求失败,状态码: ${res.statusCode}`, icon: 'none' });
      }
    },
    fail: (err) => {
      console.error('请求失败:', err);
      uni.showToast({ title: '网络错误,请检查连接', icon: 'none' });
    }
  });
}

解释:

这段代码的功能是在前端通过 API 请求获取项目列表,通常应用于 Vue 或 UniApp 项目中,调用后端接口获取数据,并将数据绑定到页面中的项目列表进行展示。以下是对该代码逻辑的详细说明:

函数名称

loadProjects():这是一个用于发起网络请求获取项目列表的函数。

功能概述

  • 该函数通过 uni.request() 发送一个 HTTP GET 请求,从后端获取排序后的项目列表,并将获取到的数据绑定到前端页面的数据属性中,以便展示项目列表。

详细解析

  1. 发起请求:函数使用 uni.request() 发起 HTTP GET 请求,请求的 URL 是后端提供的 API 接口,返回项目列表,并且按照项目名称进行排序。
  2. 请求成功处理
    • 请求成功后,回调函数首先检查响应的状态码是否为 200,表示请求成功。
    • 然后提取响应的数据,检查数据是否包含项目列表,并且项目列表是一个数组。
    • 如果数据有效,则将返回的项目列表绑定到前端的 projectsfilteredProjects 属性,用于页面展示。
    • 如果数据格式不正确,系统将输出错误日志,并提示用户数据格式有误。
  3. 请求失败处理
    • 如果请求状态码不为 200,系统会输出错误信息,通知用户请求失败,并通过提示框提醒用户。
  4. 网络错误处理
    • 如果请求因为网络问题而失败,回调函数会捕获错误,显示网络错误的提示,并建议用户检查网络连接。

总结

该函数的主要功能是在前端发起 API 请求,获取项目列表,并将其展示在页面上。如果请求成功且数据格式正确,项目列表会显示在页面上;如果请求失败或数据有误,系统会输出错误信息并提示用户。这段代码处理了 API 调用、数据绑定、以及错误处理的完整流程,适用于需要从后端获取数据并动态展示的场景。

4.附加特点设计与展示

4.1按项目名进行排序、按项目类别进行排序两种排序方式

4.1.1实现思路

选择排序字段

  • 函数首先根据 sort_by 参数来选择排序字段。
  • 如果 sort_by 参数的值是 'projectteam',那么项目将按照团队名称(projectteam)进行排序。
  • 否则,默认情况下项目会按照项目名称(projectname)进行排序。

获取并排序项目

  • 使用 Django 的 ORM 方法 Project.objects.order_by() 获取所有项目数据,并按照指定字段进行排序。
  • Project 是数据库中存储项目信息的模型类。

构建 JSON 数据

  • 使用 projects.values() 获取项目的字段数据(即将查询结果转换为一个包含所有项目数据的 QuerySet)。
  • 将这个 QuerySet 转换为列表形式,以便可以将其返回为 JSON 数据。

返回 JSON 响应

  • 将项目列表作为 JSON 响应返回,使用 JsonResponse 生成响应,其中键为 'projects',值为项目的列表。

4.1.2重要的代码片段及解释

# 视图函数,用于列出所有项目
def list_projects(request, sort_by='projectname'):
    # 根据排序参数选择排序字段
    if sort_by == 'projectteam':
        projects = Project.objects.order_by('projectteam')
    else:
        projects = Project.objects.order_by('projectname')

    # 构建项目列表的 JSON 数据
    projects_list = list(projects.values())

    return JsonResponse({'projects': projects_list})

4.1.3实现成果展示:

4.2上传用户头像功能

4.2.1实现思路

前端上传:前端通过 HTML 表单(<input type="file" name="image">)将图片文件上传至服务器。

文件获取:Django 后端通过 request.FILES 对象获取上传的文件。

模型定义:在 Django 模型中使用 ImageField 来存储图片,指定上传目录,这样图片文件会被保存到服务器的特定位置。

数据库存储:图片文件存储在服务器的文件系统中,而数据库中保存的只是文件的路径,从而避免在数据库中直接存储大体积的文件。

4.2.2重要的代码片段及解释

@csrf_exempt
def add_project(request):
    try:
        # 从请求中获取数据
        projectname = request.POST.get('projectname')
        projectteam = request.POST.get('projectteam')
        projectpeople = request.POST.get('projectpeople')
        companysituation = request.POST.get('companysituation')
        projectdescription = request.POST.get('projectdescription')
        #projectimage = request.FILES.get('image')  # 获取上传的文件

        # 检查必填字段是否为空
        if not projectname or not projectteam or not projectpeople:
            return JsonResponse({
                'status': 'error',
                'message': 'Project name, team, and people are required.'
            })

        # 创建新的项目实例并保存到数据库
        project = Project(
            projectname=projectname,
            projectteam=projectteam,
            projectpeople=int(projectpeople),
            companysituation=companysituation,
            projectdescription=projectdescription,
            #image=projectimage  # 将图片赋值给项目
        )
        project.save()

        # 返回成功的 JSON 响应
        return JsonResponse({
            'status': 'success',
            'message': 'Project added successfully.',
            'project_id': project.id
        })
    except Exception as e:
        # 捕获异常并返回错误信息
        return JsonResponse({
            'status': 'error',
            'message': str(e)
        })

4.2.3实现成果展示

5.APP功能展示

项目注册

项目登录

密码错误

项目首页与关键词搜索

项目发布

6.目录说明和使用说明

6.1前端目录

/pages
/login
- login.vue
/mypage
- mypage.vue
/myproject
- myproject.vue
/publish
- publish.vue
/signup
- signup.vue
/tabbar
/chat
- chat.vue
/chatDetail
- chatDetail.vue
/index
- index.vue
/mine
- mine.vue
/project
- project.vue

/static
/unpackage
- App.vue
- index.html
- main.js
- manifest.json
- pages.json
- uni.promisify.adaptor.js
- uni.scss

6.2后端目录

djangoproject1/ # 项目根目录

├── manage.py # Django 项目管理脚本,执行命令行工具
├── djangoproject1/ # 项目配置目录(通常包含项目的全局设置)
│ ├── init.py # 表示这是一个 Python 包
│ ├── settings.py # 项目的全局配置文件
│ ├── urls.py # 项目的 URL 配置入口
│ ├── wsgi.py # WSGI 应用入口,用于部署
│ └── asgi.py # ASGI 应用入口,用于异步部署

├── myapp/ # Django 应用目录(可以有多个应用)
│ ├── init.py # 表示这是一个 Python 包
│ ├── admin.py # 管理后台的配置文件
│ ├── apps.py # 应用配置文件
│ ├── models.py # 数据模型定义
│ ├── tests.py # 测试用例
│ ├── views.py # 视图函数(API 或页面逻辑处理)
│ ├── urls.py # 应用的 URL 配置
│ └── migrations/ # 数据库迁移文件目录
│ ├── init.py # 表示这是一个 Python 包
│ ├── 0001_initial.py # 第一个迁移文件(创建模型)
│ └── ... # 其他迁移文件

├── templates/ # 存放 HTML 模板文件
│ └── app_name/
│ └── template.html # HTML 模板文件

├── static/ # 静态文件目录(如 CSS、JavaScript、图片等)
│ ├── css/
│ ├── js/
│ └── images/

├── media/ # 用户上传的文件(可以根据需要配置)

├── requirements.txt # Python 依赖包列表

└── db.sqlite3 # SQLite 数据库文件(如果使用其他数据库,这里会是配置文件)

6.3使用说明

1. 获取代码并配置环境

  • 克隆项目代码:从代码仓库(如 GitHub、GitLab)获取项目代码。
  • 安装环境依赖:分别进入前端和后端目录,安装所需依赖。

2. 检查后端服务器

  • 检查 Django 后端服务器,确保 API 正常工作,后端能与数据库正确交互。

3. 运行前端服务器

  • 启动前端开发服务器,确保 Vue 前端正常运行,并能够与后端服务器通信。

4. 测试执行

  • 功能测试:根据需求文档,对前后端功能进行全面测试,验证用户注册、登录、项目管理等主要功能。
  • API 测试:使用工具如 Postman 对后端 API 进行测试,检查接口是否正常工作,验证请求和响应的正确性。
  • 前端测试:手动测试页面的显示、数据交互、按钮功能等,确保前端各模块工作正常。
  • 集成测试:确保前后端通信正常,模拟用户行为进行端到端测试,检查权限控制。

5. 测试报告

  • 记录测试结果,特别是发现的问题和 bug,提交缺陷报告给开发团队,并跟踪修复状态。

7.单元测试

7.1测试工具:Postman

1. 安装 Postman

  • 访问 Postman 官网 并下载适用于你的操作系统的安装程序。
  • 安装完成后,打开 Postman 应用程序。

2. 基本界面介绍

  • 左侧栏:可以创建和查看请求集合(Collection),并保存请求。
  • 请求类型选择:用于选择请求方法(GET、POST、PUT、DELETE 等)。
  • URL 输入框:用于输入 API 的 URL 地址。
  • 参数区域:用于添加请求参数、请求头、请求体等。

3. 创建一个新的请求

1. 选择请求类型

  • 打开 Postman,点击顶部的 New,选择 Request 来创建一个新的请求。
  • 在请求类型选择区域中选择请求方法,例如 GETPOSTPUTDELETE。在这个例子中我们选择 POST

2. 输入 URL

  • 在输入框中输入 API 的地址。例如:http://ci86ph16222.vicp.fun/addUser/

3. 设置请求头

  • 有时你需要设置请求的头部信息,例如

    Content-Type
    

    在 Headers选项卡中,添加键值对:

    • KeyContent-Type
    • Valueapplication/x-www-form-urlencoded(表示你将发送的是表单数据)

4. 设置请求体(Body)

  • 点击 Body 选项卡,选择 x-www-form-urlencoded
  • 添加你要发送的数据键值对:
    • KeyusernameValueyh
    • KeypasswordValue123456

4. 发送请求

  • 配置好请求类型、URL、请求头和请求体之后,点击右上角的 Send 按钮。
  • Postman 会发送请求,并在界面下方显示响应,包括响应的状态码(如 200 OK)、响应时间、返回的 JSON 数据等。

5. 查看响应

  • Status:查看服务器返回的状态码,表示请求是否成功,例如 200 OK404 Not Found500 Internal Server Error 等。
  • Body:查看服务器返回的具体数据,可以是 JSON、HTML 或其他格式。
  • Headers:查看服务器返回的响应头信息。

6. 保存请求

  • 如果希望以后能够再次使用该请求,可以点击 Save 按钮,将其保存到一个新的或已有的请求集合(Collection)中。
  • 请求集合有助于将多个相关请求组织在一起,便于测试和管理。

7.2部分单元测试截图

注册测试

项目创建测试

项目查找测试

索引测试

相关说明如下:

7.3构造测试数据的思路

在项目管理系统中进行注册、项目创建、项目查找和索引的测试时,构造测试数据的思路应尽可能全面,以便覆盖各种实际场景和边界条件。以下是具体的考虑方式:

1. 注册测试数据构造思路

  • 正常注册:创建具有有效用户名和密码的测试用户,确保最基本的注册功能正常工作。
  • 边界值测试:用户名或密码的最小长度、最大长度边界值,确保系统正确处理边界输入。
  • 特殊字符测试:用户名和密码包含特殊字符、空格、大小写字母组合,以确保系统能够正确处理所有类型的输入。
  • 空值与非法值:提交空用户名、空密码、以及非法字符(如 SQL 注入),以测试系统的安全性和输入验证能力。

2. 项目创建测试数据构造思路

  • 正常项目创建:创建具有有效名称、描述、组别、需求人数的项目,验证系统可以正常创建项目。
  • 边界值和特殊输入:项目名称和描述长度的最小和最大边界值,组别名称含有特殊字符的情况,以确保系统正确处理边界输入。
  • 空字段测试:尝试创建项目时忽略某些必填字段,验证系统正确提示必填项未填。
  • 异常人数:输入人数为负数、零或不合理的大数值,以验证系统对需求人数的合理性验证。

3. 项目查找测试数据构造思路

  • 精确查找:创建特定名称和组别的项目,测试通过名称和组别进行查找是否准确。
  • 模糊查找:输入部分项目名称或描述,验证系统是否支持模糊搜索并返回正确的项目列表。
  • 无匹配测试:输入一个不存在的项目名称,验证系统是否正确返回空结果。
  • 大小写敏感性:输入不同大小写组合的项目名称,验证系统是否能够正确忽略大小写或进行区分。
  • 特殊字符查找:输入含有特殊字符的项目名称或描述,验证系统的搜索功能对特殊字符的处理是否正常。

4. 索引测试数据构造思路

  • 正常索引测试:在系统中创建多个项目,检查索引页面是否能正确列出所有项目并按照预期的顺序(如按名称或创建时间排序)。
  • 分页测试:创建大量项目,验证索引页面是否能正确分页,确保系统能够应对大量数据。
  • 排序测试:创建项目时设置不同的创建时间和组别,测试项目索引的排序功能,确保系统按照正确的顺序显示。
  • 无项目情况:在没有项目的情况下访问索引页面,确保系统能够正确处理无数据的情况,并显示适当的提示。

应对将来测试人员的***难

  • 覆盖极端和边界情况:通过测试系统的所有边界情况和极端输入,确保任何可能导致系统崩溃或异常的输入都得到正确处理。
  • 异常输入的安全性测试:特别关注 SQL 注入、XSS 等安全方面的测试,确保系统能有效地防范恶意攻击。
  • 真实场景模拟:创建具有不同规模和复杂性的项目,模拟可能遇到的各种实际场景,例如多个用户并发创建项目、多用户查找同一项目等。
  • 灵活性和用户体验:考虑到测试人员可能会检查系统的用户友好性,确保在输入错误时,系统能够提供清晰、详细且有帮助的错误信息,而不是简单的 "错误" 或 "失败"。

结论

构造测试数据时,需要尽可能地考虑各种场景,包括常见的正常使用、边界情况、异常输入和可能的恶意攻击。同时,要确保测试数据具有代表性,以模拟实际场景中可能遇到的复杂情况,从而使系统具备更好的健壮性和用户体验。在面对测试人员的***难时,通过周全的测试和对系统各个方面的充分覆盖,确保系统能够稳定运行。

8.Github代码签入记录截图

9.代码模块异常及解决方法

问题描述 尝试 是否解决 收获
后端:mybatis安装异常 修改依赖项 依赖项版本要一一对应
后端:InfoMapper、Mapper与Service无法对应 修改函数 还是django好用
后端:models主键id无法手动输入 去除id输入 数据库会自动生成主键id
后端:无法实现全局数据传输 使用花生壳进行内网穿透 实现数据互联需要使用外网
后端:CORE协议阻止前端访问 setting输入前端ip授权 CORE协议需要手动解除
前端:数据存储与同步问题 确保在onShow生命周期方法中重新加载本地存储的数据 学会了通过本地存储(uni.setStorageSync)来保持数据的持久化
前端:元素之间的间距不均匀 通过调整margin和padding,以及合理使用flex布局,改善页面各部分的间距问题 提升了对于CSS样式的掌控能力和排版优化的技巧
前端:数据更新不及时,需要在页面之间切换时数据自动刷新。 在onShow中调用数据加载方法loadProjects() 认识到页面的生命周期方法在数据更新和页面渲染中的重要作用
前后端交互:跨域访问 安装django-cors-headers库并在设置中进行配置来实现 使用域名而非硬编码的IP地址可以使代码更具可移植性
前后端交互:安全性配置 配置了ALLOWED_HOSTS,包括你的域名和任何其他允许的主机,以防止HTTP Host头攻击。 设置ALLOWED_HOSTS和使用HTTPS,可以显著减少潜在的攻击面

10.评价

值得学习的地方

​ “你知道的,我一向是相信承宇豪的。”虽然在这个作业刚开始时他是一枚纯小白,但是他具有持续学习的能力和坚持不懈的毅力,从十月二号就开始不断push我,让我得以有充足的时间来寻找适合我的编程软件,更是在我发现idea这条路走不通时能有足够的时间重新开始,可以说我能做到如此投入,他功不可没。而且最近他似乎获得了某些动力,这使他对于前端的开发具有极其强烈的积极性,他身上认真刻苦努力热情的精神是我值得学习的地方。虽然在这个卧虎藏龙的学院里强者云集,但是我依旧很荣幸能够成为他的队友,和他一起起完成这次作业。

需要改进的地方

​ 由于本人的性格偏向懒惰,因此对他的push略感厌烦,如果他能稍微晚一点提醒我ddl将至,我想我会度过一个更为舒适的国庆节(笑)。

posted @ 2024-10-10 22:32  念影苑  阅读(18)  评论(0编辑  收藏  举报