项目 | 内容 |
这个作业属于哪个课程 | 2021春季软件工程(罗杰 任健) |
这个作业的要求在哪里 | 团队项目-计划-功能规格说明书 |
一、架构与技术栈
1.整体架构
本项目的整体架构如上图所示。下面我们将对涉及的技术栈进行详细说明:
2.前端框架
采用uni-app框架来设计前端界面,支持多平台发布的同时给用户良好的使用体验。
uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、Web(响应式)、以及各种小程序(微信/支付宝/百度/头条/QQ/钉钉/淘宝)、快应用等多个平台。极大地继承了Vue.js的优势:自底向上渐进式的开发设计。
3.后端框架
采用Node.js + Express 框架管理后端数据库。
Express框架是一个基于Node.js平台的极简、灵活的web应用开发框架,主要基于Connect中间件,并且自身封装了路由、视图处理等功能。另外,得益于Node.js繁荣的生态,我们通过npm可以方便的实现对所需资源包的获取与管理。
4.数据库
采用了MySQL数据库,后端使用MySQL包提供的接口实现ORM(Object-Relational Mapping,把关系数据库的表结构映射到对象上),经过处理后返回给前端
5.云环境
采用了腾讯提供的轻量应用服务器,具体配置如下:
镜像:Ubuntu 20.04 LTS
运算组件:2核CPU、4GB内存
云SSD系统盘:80GB SSD云硬盘
流量包:1200GB流量包
二、设计与分析
1.系统层面
1.1 代码设计
- 抽象、模块化、封装
- 前端模块化
- 使用Uni-app原生组件进行开发,如tabbar,button等
- 对于特殊功能,还需要封装自定义组件,如:刷题组件,问答列表,资源列表,题目列表,卡片内容.
- 目录结构则由Uni-app推荐的目录结构进行管理.
- 后端抽象、模块化
- 后端数据抽象化
后端将数据库返回的查询结果进行封装后,以对象数组/键值对的形式返回给前端。 - 后端功能模块化
使用模块化的函数和中间件实现各种功能,利于后期扩展和维护。
- 前后端分离
前后端开发是解耦的,可以并行进行,只需要前后端共同维护一个接口文档就可以实现前期并行开发,后期便捷集成。
- 功能设计
- 接口设计
1.2 架构设计
- 界面和实现的分离
界面是呈现给用户的界面,即为前端的设计。实现是后端对数据处理返回给前端。所以我们采用了前后端分离的做法来实现界面和实现的分离。前后端通过上述定义的api接口来进行请求发送->请求响应->返回对应数据 流程来实现。前端需要对界面进行设计,并明确自己所需要的数据;后端需对管理的数据进行整合处理,对请求的数据进行返回。 - 错误处理
因为我们采用了前后端分离的方法。错误会发生在前端、后端以及服务器上。
对于前端,错误发生在界面的渲染上和一些未定义的功能行为。这一部分错误产生能在测试阶段进行捕获,并可以直接部署修改在代码上。同时在产品发布后,可以针对反馈信息来进行错误的收集。
对于后端,错误发生在数据的处理上,包括了数据不存在,权限失败等错误行为,这里在实现阶段定义了对应的错误号,体现在对应的返回数据中,前端对于返回数据中的错误号,显示对应的错误提示信息。这些错误同样可以在测试和反馈阶段进行捕获。另一方面,有些错误是系统允许的,需要对用户的非法行为做出应对,属于程序的正常行为。
对于服务器,错误的产生源于网络、服务器性能等多种不可抗因素,这里不再赘述处理方法。 - 应对变化的灵活性
首先我们前端采用了基于Vue.js的uni-app框架。Vue.js是一款从底至顶渐进式的开发框架。可以灵活地支持组件的复用。
其次我们采用了前后端分离的模式,对于前后端通过api接口进行连接,二者相对独立。对于需求的变化可以在不影响接口的前提下在各自模块中进行修改;对于错误处理,可以按照上述方式进行灵活修改。
最后,基于我们的团队协作原则,对于开发测试中的难题,团队里可以进行灵活协商。
1.3 测试设计
- 单元测试
- 前端单元测试
由于前端使用的是基于Vue.js的uni-app框架,对此我们采用了Vue.js官方的单元测试实用工具库——Vue Test Utils。同时为了使测试尽可能覆盖全面,我们采用了以下模式进行测试:
- 构建基于Jest的Vue单元测试环境
Jest包含着karma + mocha + chai + sinon 的所有常用功能,相对而言Jest更加全面。这里采用Jest进行第一版的简单测试,对每一个Vue组件进行测试 - 使用Vue Test Util 提高测试编码效率
基于Vue Test Util丰富的官方文档及实用API开展进一步的测试,同时根据同步的DOM更新,对DOM事件的响应进行测试。 - 对复杂场景进行测试
目标上,争取mock掉目标组件范围外所有不好测试的模块。根据单元测试的粒度,在测试代码中插入断言。
- 后端单元测试
- 代码编写
由于后端使用基于Node.js的Express框架,因此我们需要完成的后端代码包括:入口文件、路由中间件、mysql中间件、身份认证中间件。 - 单元测试
我们使用Express进行模块化设计与实现,因此,单元测试针对的是我们所编写的模块。
就拿上文提到的路由中间件为例,假设我们编写了一个路由文件user.js
,并且包含一个匹配路径后的http get
方法:
router.get("/",verifyRight("get/users"),async(req,res,next)=>{
var query = req.query.query;
var pagenum =req.query.pagenum == undefined?1:req.query.pagenum;
var pagesize = req.query.pagesize ==undefined?5:req.query.pagesize;
var data = {};
let sql = `select user.id id,username,email,phone,rolename from user
left outer join role on roleid = role.id limit ${(pagenum-1) *pagesize},${pagesize}`
if(query !== ""){
sql = `select user.id id,username,email,phone,rolename from user
left outer join role on roleid = role.id where username like '%${query}%' limit ${(pagenum-1) *pagesize},${pagesize}`
}
var result = await sqlQuery(sql);
data["users"] = result;
data["pagenum"] = pagenum;
sql = `select count(*) from user`
if(query !== ""){
sql = `select count(*) from user where username like '%${query}%' `
}
var result = await sqlQuery(sql);
data["total"] = result[0]["count(*)"] ;
res.json(resBody(data,1,"获取成功"))
})
这个路由中间件主要是进行路由匹配、权限认证、异步回调处理并返回结果等功能。
如果我们想对这个中间件进行测试,可以借助测试框架Mocha
。我们可以创建user-test
工程来对user.js
进行相关测试,其中包括对这个http get
的测试。
在项目工程下配置好Mocha
后,我们在默认目录test
下编写user-test.js
的测试。
通过在user-test.js
中导入assert
模块以及user.js
文件的user
模块,我们可以对调用所要测试的方法后res
的结果进行断言,即可验证所测方法行为的正确性。
最后,我们就可以利用Mocha
运行测试了。
通过在package.json
中添加npm命令:
{
...
"scripts": {
"test": "mocha"
},
...
}
然后在测试工程目录的terminal下运行命令:npm test
。默认情况下,所有测试都会自动执行,最后会在命令行下显示各个测试通过与否。
- 压力测试
- 测试内容
做题功能是我们“题士”产品的最核心的模块,根据目前业务的需要,我们需要测试能否支持500的并发做题量。 - 测试场景设置
使用类似于LoadRunner
的现有工具模拟真实用户,采取逐步增加用户数(每分钟增加用户数5人)对做题功能进行并发操作,达到500人为止;当并发数达到500后则继续运行一段时间(60分钟)。 - 服务器状态监视
由于我们购买的是腾讯云的服务器,腾讯云为我们提供了对数据库、CPU/内存的占用率等信息,结合实际产品提供服务的情况,我们可以判断系统是否能通过压力测试。 - 测试结果收集与分析
由于产品后端部署环境有很多参数可以调节,例如,MySQL可以配置max_connections
,thread_cache_size
,back_log
等参数,因此,我们可以收集设置不同参数下系统的状态信息与当前并发数,构造关系表格进行分析,理想情况下应该能找出并发瓶颈。
- 真实测试
真实测试是对我们的系统进行一系列实际使用时会遇到的真实情况的模拟。我们团队将从以下方面对真实的情况进行分类并进行测试
- 功能测试
- 手动测试,模拟真实用户进行功能实现与否的测试
- 自动化测试,设计测试用例,实际上就是针对代码的单元测试。
- 专项测试
- 兼容性测试,使用不同设备,不同型号,不同分辨率对ui进行测试
- 安装卸载升级测试
- 交叉事件测试,测试考察点如下: 包含运行时接收来电/短信/消息推送, 运行时出现系统弹窗, 运行时切换外部设备等。
- 用户体验度测试,包含:界面设计,功能易用性,横竖屏切换,系统功能响应
- 稳定性测试通过测试工具实现在一定时间范围内的无序操作, 来检测应用的稳定运行能力, 重点在于考察应用在测试期间出现程序无响应或闪退的频率. 使用Monkey,UICrawler,Maxin
- 客户端性能测试
测试考察点如下: 包含CPU/内存占用, 界面流畅度, 流量/电量消耗, 启动时间等. - 服务端性能测试
APP 应用的服务端性能测试可以依赖主流常见的性能测试工具来实现. 例如: LoadRunner, JMeter等.
1.4 性能分析
“题士”产品可能面临大量用户同时刷题的大数据、高并发情形。
前后端分离,对于前端的资源可以使用nginx等效率高的服务器,并且数据是在前端渲染,不是在服务端通过jsp、freemarker等渲染后返回前端,相当于把原本服务端处理的任务分散到用户端浏览器,可以很大程度的提高页面响应速度。
但是前后端分离需要解决跨域的问题,我们打算在后端进行跨域控制,摒弃session+cookie的身份认证模式,转而使用token验证方式。后端采用Node.js,因其单(主)线程、异步I/O、事件循环等技术,本身是有利于高并发的。
2.业务流程层面
2.1 用户操作
- 输入数据
针对产品的功能,用户在使用程序过程中产生的数据体现在以下几个方面:
- 用户登录的账号信息
账号信息包括账号(这里采用的是用户的手机号),密码,和手机验证码。 - 问答社区的评论数据
评论数据包括文字,图片。主要是用于社区中用户用于交流表达产生的可视化数据。 - 资源社区的资源数据
用户可以上传的数据包括上文件,图片资源,并以相关文字加以描述。
- 支持操作
本产品可以支持的用户操作在功能介绍中已详细说明。这里主要将用户在使用软件时的事件视为对程序的某些“输入”。例如用户的点击行为,刷新行为,滑动行为等。
2.2 异常处理
- 针对输入数据
- 账号表单验证及后端数据库验证
对于登陆页面,会对填入的数据进行表达验证:不允许输入空白且不符合要求的手机号;不允许输入空白密码或者验证码。在响应登陆行为时,会在后端进行相对应的验证,以免不法登录。 - 限制评论数据的输入
我们设计了对应的文本框进行文本输入,同时加入上传图片功能对评论加入图片。以上行为限制了输入数据,同时对于非法格式,上传失败。 - 限制资源上传
类似对评论数据的限制,我们同样对上传功能进行限制。
- 针对用户操作行为
用户的操作行为的限制基于功能的设置。对于未定义行为不给予响应;对于权限外的行为,抛出非法权限警告;对于频繁操作的行为,抛出响应等待警告。
三、更新日志
时间 | 更新内容 |
2021-04-20 10:00 | 按照班级作业要求完成技术规格说明书 |