路漫漫其修远兮,吾将上下而求索。|

oolone

园龄:6个月粉丝:0关注:1

软件工程第二次结对作业

软件工程第二次结对作业

这个作业属于哪个课程 https://edu.cnblogs.com/campus/fzu/SE2024
这个作业要求在哪里 https://edu.cnblogs.com/campus/fzu/SE2024/homework/13281
这个作业的目标 实现一个“ProjectPartner”的校园项目合作平台的WEB、APP或小程序(三选一)
学号-姓名 102202149-詹镇壕
学号-姓名(合作队友) 102202142-黄悦佳
队友博客链接 https://www.cnblogs.com/dust4399/p/18457455
项目Github仓库链接 https://github.com/oolone/102202149-102202142

一、PSP 表格

PSP表格 预估耗时(小时) 实际耗时(小时)
项目规划 11.5 13.5
· 估计完成任务需要多少时间 0.5 0.5
· 确定和熟悉开发工具 10 12
· 分配工作 1 1
项目开发 35 36
· 需求分析 1 1
· 代码规范制定 1 1
· 框架设计 3 3.5
· 具体开发 24 26
· 界面美化 2 2.5
· 代码审查 2 1
· 测试(自我测试,可能需要多次) 2 1
报告 3.5 4
· 博客编写 2 2.5
· 测试说明 1 1
· 计算工作量 0.5 0.5
总计 50 53.5

二、分工合作表格

人员 任务分工
詹镇壕 - 负责需求分析,确定小程序的具体功能需求。
- 进行小程序的整体架构设计和页面布局规划。
-负责页面美化和数据查找
-参与部分页面的实现
- 参与代码审查,确保代码质量符合规范。
- 编写博客作业和测试报告。
- 统计工作量。
黄悦佳 - 制定代码规范,确保团队开发过程中有统一的代码风格。
- 参与需求分析,完善小程序功能需求。
- 根据设计进行具体的代码开发工作,实现各个功能模块。
- 负责数据库和程序的后端服务。
- 进行自我测试,查找并修复代码中的漏洞和错误。
- 协助博客编写和测试报告。

三、项目思路描述与设计实现说明

1、解题思路描述

(1)需求分析

  • 目标用户群体:大学生,特别是寻求跨专业合作的学生。
  • 用户需求:寻找合作伙伴、项目管理、沟通协调、资源共享。

(2)功能实现

用户注册与登录

  • 使用微信小程序的云开发功能,创建用户集合存储用户信息。
  • 注册时,进行用户名和密码的基本验证,并通过云函数进行密码加密后存储。
  • 登录时,通过云函数对比密码,确保安全性。

项目查看

  • 项目信息存储在云开发的数据库中,通过查询接口获取项目列表。
  • 实现一个搜索算法,根据用户输入的关键词,进行模糊查询。
  • 项目列表页展示项目基本信息,点击进入项目详情页。

项目发布

  • 提供一个表单页面,用户可以填写项目的各种信息。
  • 提交后,通过云函数进行数据验证,然后存储到数据库。

项目管理

  • 每个项目有一个独立的页面,展示项目的所有信息和操作。
  • 提供接口供用户编辑和删除项目,操作后实时更新数据库。

即时通讯

  • 使用微信小程序的即时通讯接口,为用户提供聊天功能。
  • 聊天信息存储在云开发的数据库中,确保信息的持久化。

个人主页

  • 用户可以编辑自己的个人信息,包括学号、性别、学院、联系方式等。
  • 提供一个表单供用户输入信息,通过云函数验证后更新到数据库。

隐私设置

  • 用户可以在个人设置中管理自己的隐私选项,决定哪些信息是公开的。

(4)用户界面设计

  • 简洁直观的用户界面,方便用户快速上手。
  • 页面美化,统一页面结构和色彩,增添图片,避免单调。
  • 清晰的导航结构,方便用户找到所需功能。
  • 响应式设计,确保在不同设备上都有良好的用户体验。

(5)技术选型

  • 平台类型:小程序。
  • 开发工具:微信开发者工具。
  • .js文件:编写小程序的逻辑代码,包括页面的交互逻辑、数据处理、网络请求等。
  • .json文件:用于配置小程序的全局设置和页面的配置信息。
  • .wxml文件:类似于网页中的 HTML 文件,用于描述小程序的页面结构。
  • .wxss文件:类似于网页中的 CSS 文件,用于定义小程序页面的样式。
  • 数据库:微信开发者工具自带云开发。
  • 云服务:微信开发者工具自带云开发。

(6)测试与反馈

  • 进行单元测试、集成测试和用户测试,确保功能正常运行。

2、主要页面设计实现说明

登录注册流程图

登录

验证成功

验证失败

注册

已注册

未注册

添加成功

添加失败

开始

登录/注册

输入账号密码

数据库验证

更新全局变量

跳转到首页

显示错误信息

输入注册信息

检查学号是否已注册

添加用户到数据库

跳转到登录页

登录注册关键代码

1、登录验证:

select: function() {
  const account = this.data.account;
  const password = this.data.password;
  // ...省略部分代码...
  db.collection('test').where({
    stuid: account
  }).get({
    success: function(res) {
      if (res.data.length > 0 && res.data[0].pswd === password) {
        // 登录成功,更新全局变量
        app.globalData.userInfo = res.data[0].stuid;
        // ...省略部分代码...
        wx.switchTab({
          url: '/pages/index/index',
        });
      } else {
        // 登录失败,显示错误信息
        wx.showToast({
          title: '账号或密码错误',
          icon: "none"
        });
      }
    },
    // ...省略部分代码...
  });
},

2、注册逻辑:

async addFun01() {
  const checkRes = await db.collection('test').where({
    stuid: this.data.stuid
  }).get();
  if (checkRes.data.length > 0) {
    wx.showToast({
      title: '该学号已被注册',
      icon: 'none'
    });
    return;
  }
  // ...省略部分代码...
},

首页流程图

开始

页面加载

调用fetchLatestRecords

从云数据库获取数据

更新页面数据

显示项目信息

下拉刷新

调用upper函数

显示加载提示

重新获取数据

更新页面数据

上拉加载更多

调用lower函数

显示加载提示

加载更多数据

导航事件

跳转到详情页或问题页

首页关键代码

1、获取数据库数据:

fetchLatestRecords: function() {
  db.collection('project')
    .orderBy('createdAt', 'desc')
    .limit(12)
    .get()
    .then(res => {
      console.log('获取到的记录:', res.data);
      this.setData({
        records: res.data,
        feed: res.data,
        feed_length: res.data.length
      });
      wx.setStorageSync('latestRecords', res.data);
    })
    .catch(err => {
      console.error('获取记录失败:', err);
    });
},

2、下拉刷新逻辑:

upper: function() {
  wx.showNavigationBarLoading();
  this.refresh();
  console.log("upper");
  setTimeout(function(){wx.hideNavigationBarLoading();wx.stopPullDownRefresh();}, 2000);
},

个人项目流程图

开始

页面加载

调用fetchLatestRecords

从云数据库获取数据

更新页面数据

显示项目信息

下拉刷新

调用upper函数

显示加载提示

重新获取数据

更新页面数据

上拉加载更多

调用lower函数

显示加载提示

加载更多数据

新建项目

跳转到新建项目页面

查看项目详情

跳转到项目详情页面

聊天页面流程图

开始

点击按钮

设置输入框焦点

输入文字

更新输入值

点击添加联系人

显示提示

点击导航

跳转到联系人页面

输入特定值

隐藏键盘

聊天页面关键代码

1、输入框焦点控制

bindButtonTap: function() {
  this.setData({
    focus: Date.now()
  });
},

2、输入替换:

bindReplaceInput: function(e) {
  var value = e.detail.value;
  var pos = e.detail.cursor;
  if(pos != -1){
    var left = e.detail.value.slice(0,pos);
    pos = left.replace(/11/g,'2').length;
  }
  return {
    value: value.replace(/11/g,'2'),
    cursor: pos
  };
},

个人信息页面

开始

页面加载

获取全局用户信息

获取用户数据库信息

更新页面数据

退出登录

清除全局用户信息

跳转到登录页面

修改信息

跳转到修改页面

我的项目

跳转到我的项目页面

四、附加特点设计与展示

特色展示

页面设置刷新功能:通过上划页面,快速刷新页面。

//网络请求数据, 实现首页刷新
//refresh0 函数,这个函数的目的是从网络请求数据来刷新首页
  refresh0: function(){
    var index_api = '';
    util.getData(index_api)
        .then(function(data){
          //this.setData({
          //
          //});
          console.log(data);
        });
  },
  //使用本地 fake 数据实现刷新效果
//getData 函数,这个函数使用本地的假数据(fake data)来模拟刷新效果。
//它从 util.getData2 获取数据,并使用 this.setData 来更新页面数据。
  getData: function(){
    var feed = util.getData2();
    console.log("loaddata");
    var feed_data = feed.data;
    this.setData({
      feed:feed_data,
      feed_length: feed_data.length
    });
  },
//refresh 方法,这个方法首先显示一个提示,告知用户正在刷新。
//然后,使用 util.getData2 获取数据,并更新页面。
//最后,设置了一个定时器,在3秒后显示刷新成功的提示。
  refresh: function(){
    wx.showToast({
      title: '刷新中',
      icon: 'loading',
      duration: 3000
    });
    var feed = util.getData2();
    console.log("loaddata");
    var feed_data = feed.data;
    this.setData({
      feed:feed_data,
      feed_length: feed_data.length
    });
    setTimeout(function(){
      wx.showToast({
        title: '刷新成功',
        icon: 'success',
        duration: 2000
      })
    },3000)

  },

主页设置自动播放的图片轮播组件

页面更加美观,不单调

<!-- 滚动图片 -->
  <swiper class="activity" indicator-dots="{{indicatorDots}}"
          autoplay="{{autoplay}}" interval="{{interval}}" duration="{{duration}}">
    <block wx:for="{{imgUrls}}">
      <swiper-item>
        <image src="{{item}}" class="slide-image" width="355" height="155"/>
      </swiper-item>
    </block>
  </swiper>

功能展示

-登录查看主界面退出登录

  • 加入项目

  • 项目创建发布后,主页会自动加载最近的几个项目

  • 退出项目

  • 删除项目

-聊天功能实现

-搜索功能实现

  • 修改个人信息

五、目录说明和使用说明

目录说明

# 校园项目伙伴招募小程序项目目录说明
## 项目结构
│  .eslintrc.js          #用于代码风格检查的配置文件。
│  .gitignore            #指定哪些文件或目录不需要被 Git 跟踪。
│  app.js                #小程序的入口文件。
│  app.json               #小程序的全局配置文件
│  app.wxss                #小程序的全局样式文件。
│  project.config.json      #项目配置文件。
│  project.private.config.json      #项目配置文件。
│  README.md          #项目说明文档。
│  tree.txt            #目录结构文本文件。
│  
├─.git                  #用于版本控制,包含配置文件、钩子脚本、信息和日志等。
│  │  config
│  │  description
│  │  HEAD
│  │  index
│  │  
│  ├─hooks
│  │      README.sample
│  │      
│  ├─info
│  │      exclude
│  │      
│  ├─logs
│    │  HEAD
│    │  
│    └─refs
│        └─heads
│               master
│              
├─cloud                 #存放与云环境相关的文件。
├─data                  #用于存放数据文件。
├─images                #页面图标的图标存放处,burger.png
burger_focus.png
│      chat.png
│      chat_focus.png
│      discovery.png
discovery_focus.png
│      index.png
│      index_focus.png
│      
├─pages                  #页面存放
│  ├─answer              #项目详情
│  │      answer.js
│  │      answer.json
│  │      answer.wxml
│  │      answer.wxss
│  │      
│  ├─chat                #聊天页面
│  │      chat.js
│  │      chat.json
│  │      chat.wxml
│  │      chat.wxss
│  │      
│  ├─contact              #对话页面页
│  │      contact.js
│  │      contact.json
│  │      contact.wxml
│  │      contact.wxss
│  │      
│  ├─createpro            #创建项目页
│  │      createpro.js
│  │      createpro.json
│  │      createpro.wxml
│  │      createpro.wxss
│  │      
│  ├─discovery            #个人项目页
│  │      discovery.js
│  │      discovery.json
│  │      discovery.wxml
│  │      discovery.wxss
│  │      
│  ├─forget                #找回密码
│  │      forget.js
│  │      forget.json
│  │      forget.wxml
│  │      forget.wxss
│  │      
│  ├─index                #首页(查找项目)
│  │      index.js
│  │      index.json
│  │      index.wxml
│  │      index.wxss
│  │      
│  ├─login                #登录注册页面
│  │      login.js
│  │      login.json
│  │      login.wxml
│  │      login.wxss
│  │      
│  ├─mine                #修改个人信息
│  │      mine.js
│  │      mine.json
│  │      mine.wxml
│  │      mine.wxss
│  │      
│  ├─more                #个人信息页
│  │      more.js
│  │      more.json
│  │      more.wxml
│  │      more.wxss
│  │      
│  ├─myproject          #个人项目页(备用版本)
│  │      myproject.js
│  │      myproject.json
│  │      myproject.wxml
│  │      myproject.wxss
│  │      
│  ├─question          #项目详情
│  │      question.js
│  │      question.json
│  │      question.wxml
│  │      question.wxss
│  │      
│  ├─select            #搜索功能
│  │      select.js
│  │      select.json
│  │      select.wxml
│  │      select.wxss
│  │      
│  └─wait              #等待审核页面wait.js
wait.json
wait.wxml
wait.wxss
│          
└─utils                #存放工具函数文件
        util.js

使用说明

1、用微信扫描二维码进入登录页面。

  • 可以注册账号后使用注册的账号进行登录。
  • 也可以使用测试账号进行登陆(102202142,123456)。
    (由于小程序暂未上线,只有体验人员可以进行体验程序,如需体验,请联系程序管理员赋予微信账号体验权限)
    管理员联系方式:qq:2644961392 weichat:hyj6625

2、进入首页后:

  • 如果此时没有项目,可进入到项目发布页(第二页)进行项目发布。
  • 点击项目,可以进入项目详情页,在该页面可以查看项目详细信息,并在下方选择加入项目(点赞、收藏、评论功能暂未开发)。

3、项目发布页:

  • 填写相关信息进行发布,然后回到首页进行刷新可以更新页面,同时个人项目也可以进行更新。

4、聊天页面:

  • 可以查看最近的聊天选项,点击后进入聊天页面。

5、个人信息页:

  • 可以修改自己的个人信息,更新图像等,图像可以使用微信头像。

对于测试人员来说,可以按照以下步骤运行网页:

  • 1、使用微信扫描二维码进入小程序。
  • 2、使用注册账号或测试账号登录。
  • 3、在首页查看是否有项目,若没有可进入项目发布页发布项目。
  • 4、点击项目进入项目详情页查看详细信息。
  • 5、尝试在项目发布页发布项目并在首页刷新查看更新情况。
  • 6、进入聊天页面查看聊天选项,但需注意聊天功能暂未完全开发。
  • 7、进入个人信息页修改个人信息和更新图像。

六、单元测试

1、测试工具选择

  • 我们选用的测试工具是微信小程序开发工具中自带的测试框架。这个框架基于 Jest,是一个广泛使用的 JavaScript 测试框架,它提供了丰富的匹配器和丰富的断言方法,非常适合用于单元测试。

2、学习单元测试的途径

  • 官方文档:阅读 Jest 官方文档,了解其基本使用方法和高级特性。
  • 在线教程:通过在线平台如慕课网、极客时间等学习单元测试的基本概念和实践技巧。
  • 社区交流:在 CSDN、GitHub 等社区查看相关问题和讨论,学习他人的最佳实践。
  • 实践操作:通过实际编写测试用例,逐步掌握单元测试的编写和调试技巧。

3、简易教程

  • 安装依赖:确保你的项目中安装了 Jest 和相关的小程序适配器,例如:
npm install jest @jest-runner/mini-program-jest
  • 配置 Jest:在项目的 package.json 中添加 Jest 配置:
{
  "scripts": {
    "test": "jest"
  }
}
  • 编写测试用例:创建一个测试文件,例如 sum.test.js,并编写测试用例:
const { sum } = require('./mathUtils');

test('adds 1 + 2 to equal 3', () => {
  expect(sum(1, 2)).toBe(3);
});

test('adds 0.1 + 0.2 to equal 0.3', () => {
  expect(sum(0.1, 0.2)).toBe(0.3);
});
  • 运行测试:
    在命令行中运行 npm test,Jest 将自动找到并执行所有测试用例。

项目部分单元测试代码(登录注册功能)

const { wx, app } = require('jest-wx-mock');
const myUtils = require('./utils'); // 登录和注册逻辑在 utils.js 文件中

// 模拟全局变量
app.globalData = {
  userInfo: null,
  stuname: null,
  avatarurl: null
};

// 模拟数据库操作
const db = {
  collection: jest.fn(),
};

// 模拟 wx.showToast 和 wx.showLoading
wx.showToast = jest.fn();
wx.showLoading = jest.fn();
wx.hideLoading = jest.fn();
wx.switchTab = jest.fn();
wx.navigateTo = jest.fn();

// 模拟数据库查询成功的情况
db.collection.mockImplementation((collectionName) => {
  if (collectionName === 'test') {
    return {
      where: jest.fn().mockReturnThis(),
      get: jest.fn().mockImplementation((options) => {
        if (options.success) {
          options.success({
            data: [{ stuid: 'mockedStuid', nickname: 'mockedName', avatarid: 'mockedAvatar' }]
          });
        }
      })
    };
  }
});

// 测试登录功能
test('login with correct account and password', () => {
  const account = 'mockedStuid';
  const password = 'correctPassword';
  myUtils.select.call({ data: { account, password } });
  expect(wx.showToast).toHaveBeenCalledWith({
    title: '密码错误',
    icon: 'none',
  });
  expect(wx.switchTab).toHaveBeenCalledWith({
    url: '/pages/index/index',
  });
});

// 测试注册功能
test('register with new stuid', () => {
  const stuid = 'newMockedStuid';
  const telepnum = '12345678901';
  const captcha = 'mockedCaptcha';
  const pswd = 'newPassword';
  const conpaswd = 'newPassword';
  myUtils.addFun01.call({ data: { stuid, telepnum, captcha, pswd, conpaswd } });
  expect(wx.showToast).toHaveBeenCalledWith({
    title: '注册成功',
    icon: 'success',
  });
});

// 测试注册时学号已被注册的情况
test('register with existing stuid', () => {
  const stuid = 'mockedStuid';
  const telepnum = '12345678901';
  const captcha = 'mockedCaptcha';
  const pswd = 'newPassword';
  const conpaswd = 'newPassword';
  db.collection.mockImplementation((collectionName) => {
    if (collectionName === 'test') {
      return {
        where: jest.fn().mockReturnThis(),
        get: jest.fn().mockImplementation((options) => {
          if (options.success) {
            options.success({
              data: [{ stuid: 'mockedStuid' }] // 模拟已存在的学号
            });
          }
        })
      };
    }
  });
  myUtils.addFun01.call({ data: { stuid, telepnum, captcha, pswd, conpaswd } });
  expect(wx.showToast).toHaveBeenCalledWith({
    title: '该学号已被注册',
    icon: 'none',
  });
});

4、构造测试数据的思路

  • 覆盖所有分支:确保测试数据能够覆盖代码中的所有条件分支,包括正常流程和异常流程。
  • 边界值分析:选择边界值作为测试数据,例如最小值、最大值、特殊值等,这些往往容易暴露问题。
  • 等价类划分:将输入数据划分为有效的和无效的等价类,确保每个等价类都有测试用例。
  • 异常情况考虑:考虑空值、负数、非预期格式等异常输入,以及这些输入对系统的影响。
  • 依赖数据:对于依赖其他数据或状态的测试,确保所有依赖项都已正确设置。

5、如何应对未来测试人员的为难

  • 全面覆盖:确保测试覆盖率达标,所有代码路径都被测试到,包括边缘情况。
  • 自动化测试:建立自动化测试流程,减少人工干预,提高测试的一致性和可重复性。
  • 持续集成:将单元测试集成到CI/CD流程中,确保每次代码提交都会自动运行测试。
  • 代码审查:定期进行代码审查,检查测试代码的质量,确保测试的有效性。
  • 测试用例管理:使用测试用例管理工具,记录每个测试用例的详细信息,包括测试数据和预期结果。
  • 性能监控:监控应用的性能,确保在不同负载下都能满足性能要求。
  • 用户反馈:收集用户反馈,对用户报告的问题进行复现和测试,确保这些问题被解决。
  • 测试数据隔离:确保测试数据与生产数据隔离,避免测试活动对生产环境造成影响。
  • 测试数据的多样性:引入多样化的测试数据,包括不同语言、文化、时区等,确保应用的国际化和本地化。
  • 模拟复杂场景:模拟复杂的用户交互和并发操作,确保系统在复杂场景下仍然稳定。

七、Github的代码签入记录截图

  • 说明:部分代码合作使用微信小程序开发自带的功能,github只有几次签入记录。

八、代码模块异常或结对困难及解决方法

问题一(代码模块异常)

  • 问题描述:进行个人信息修改模块编写时,原本的设计是进入个人页立即刷新,从云数据库获取个人信息。后发现这样每次进入都必须重新加载页面,效率低且浪费时间性能。
  • 尝试:改进代码,仅在首次进入页面时,即onLoad()中加载数据,不在onShow()中刷新。
  • 同时,在修改个人信息后同时调用刷新函数,保证信息的及时修改。
  • 改进后代码
  • 是否解决:是
  • 收获:程序流程的合理设计是保证有效高质量的代码编写,程序运行的基础。

问题二

  • 问题描述:微信云数据库实时刷新存在问题。不同设备上进行账号注册,项目创建,云数据库存在其他设备的账号信息,但却无法在注册设备以外的设备上登录。同时发现在同一设备上注册相同学号的账号,能够正常报错,但是在其他设备上却可以创建。
  • 尝试:怀疑只能从云数据库读取本地上传的数据。
  • 是否解决:否
  • 收获:代码编程,软件开发困难重重,任重道远,还需努力学习

九、评价队友

对队友黄悦佳的评价

在校园项目伙伴招募小程序的项目开发中,黄悦佳同学作为我的队友,他的工作表现给我留下了深刻的印象。以下是对他的综合评价,包括值得学习的地方以及可能需要改进的地方。

值得学习的地方

  1. 技术能力:黄悦佳同学在技术上的专业能力非常强,他对前端和后端的开发都有深入的了解,这对于项目的顺利进行至关重要。他的技术能力是我们团队的宝贵财富。

  2. 责任心:他对待工作非常认真,总是能够按时完成分配给他的任务,并且质量很高。他的责任心确保了项目的稳定性和可靠性。

  3. 团队合作精神:黄悦佳同学在团队中总是乐于助人,他愿意分享自己的知识和经验,帮助我解决问题,这对于提升团队的整体效率非常有帮助。

  4. 自我驱动:他具有很强的自我驱动力,能够在没有外部压力的情况下自我激励,不断推动项目向前发展。

  5. 学习能力:面对新技术和挑战,黄悦佳同学展现出了快速学习和适应的能力,这对于项目的创新和进步非常重要。

需要改进的地方

  1. 时间管理:虽然黄悦佳同学能够完成他的工作,但有时他的时间管理可以更加优化。在项目后期,一些任务的延期对整体进度产生了影响。

  2. 沟通方式:在团队合作中,沟通是非常关键的。黄悦佳同学在表达自己的想法时,有时可以更加直接和清晰,以便更快地达成共识。

  3. 风险预见:在项目开发过程中,预见潜在的风险并提前准备解决方案是非常重要的。黄悦佳同学在未来的项目中可以更加注重这一点,以减少意外情况对项目的影响。

总的来说,黄悦佳同学是一位非常优秀的团队成员,他的许多品质都值得我们学习。同时,通过在这些方面进行改进,他将能够在未来的项目中发挥更大的作用。我期待与他再次合作,并看到他在未来取得更大的成就。

本文作者:oolone

本文链接:https://www.cnblogs.com/oolone/p/18457202

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   oolone  阅读(7)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起