2020软工实践第二次结对作业

这个作业属于哪个课程 https://edu.cnblogs.com/campus/fzu/SE2020
这个作业要求在哪里 https://edu.cnblogs.com/campus/fzu/SE2020/homework/11277
这个作业的目标 结对实现学术家族树的编程,学习前端内容和单元测试的知识
学号 031802223 刘东权 031802219 林璟
Github地址 https://github.com/DQbryant/031802223-031802219

一、PSP表格

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

二、具体分工

  • 我负责的是html、css,并修改了部分js,准备测试数据,以及撰写博客。
  • 我的队友负责js的部分,实现对输入字符串的解析和学术家族树的呈现,以及单元测试。

三、解题思路和设计实现

实现思路

项目使用了bootstrap+jquery+echarts,采用传统的html+css+js实现。作业要求解析固定格式的字符串并生成对应的学术家族树图,所以首先要解析字符串,通过三个换行符分隔每棵树的字符串,分别解析各个字符串的第一行(生成导师信息),第二行(块)获得学生信息,后面逐行获取各个学生的技能或经历信息,并将每个学生的信息存入map中,解析完每棵树的字符串后生成对应json如{name:"张三",children:[{name:"2018级研究生",children:[{name:"刘四",value:""},{name:"王五",value:""}]},{name:"2019级本科生",children:[{name:"赵四",value:"},{name:"李五",value:""}]}]},再使用echarts.js生成每个json的树图,点击时显示学生技能而不是展开学生节点,因为经测试,设置学生节点可展开,将每个技能或经历作为其子节点由于echarts的缘故不够美观,因此将学生技能和经历设置为点击学生节点后在左侧显示。

关键数据流图

核心代码片段

/**
 * 将输入的文本转为需要的js对象
 * @param {*} treeText 输入的文本
 */
function parse(treeText) {
    let lines = treeText.split('\n');
    let data = new Object();
    let map = new Map();
    data.name = lines[0];
    if (lines[0].slice(0, 2) !== '导师') {
        throw new Error('ERROR: 导师行不正确,请注意每组数据之间有两行空行');
    }
    data.children = new Array();
    // 对每一行进行解析
    for (let i = 1; i < lines.length; i++) {
        if (lines[i] === '') continue;
        // 当前行是学生列表
        if (!isNaN(lines[i].slice(0, 4))) {
            var children = new Object();
            console.log(lines[i].search('级博士生|级硕士生|级本科生'))
            if (lines[i].split(':').length <= 1 || (lines[i].search('级博士生|级硕士生|级本科生')) == -1) {
                throw new Error('ERROR: 学生信息解析不正确');
            }
            children.name = lines[i].split(':')[0];
            children.children = new Array();
            // 对于每一个学生
            lines[i].split(':')[1].split('、').forEach(item => {
                var t = new Object();
                t.name = item;
                t.value = '暂无';
                children.children.push(t);
                // 将当前对象存入map方便后面修改技能信息
                map.set(item, t);
            })
            data.children.push(children);
            // 当前行是技能信息
        } else {
            let [name, skill] = lines[i].split(':')
            // 如果技能文字为空
            if (!skill) {
                throw new Error('ERROR: 节点技能输入不正确');
            }
            if (!map.get(name)) {
                throw new Error("学生 " + name + "不存在")
            }
            map.get(name).value = skill;
        }

    }
    const domText = '<div class="graph" style="width: 100%;height:350px;"></div>';
    $(".graph-wrapper").append(domText);
    return data;
}

该函数的功能是将输入的文本转为需要的 js 对象。首先将文本按行分割。第一行默认是导师行,将导师的节点作为树的根节点,之后对每一行进行解析。若前4个均为数字,则为学生列表行,因为输入数据的分隔符比较明显,所以直接通过 ':' 和 ‘、’ 进行分割后解析。同时,为了避免后面读入技能信息时进行树的遍历,这里将每一个叶节点暂存到了 map 里,这样,后面就可以以 O(1) 的时间来更新对应节点的技能。

五、特点设计和展示

创意独到之处

  • 支持文件上传,保存学术家族树图

设计的意义

  • 文件上传:可以方便用户在本地编辑用例数据,组织更方便。
  • 保存学术家族树图:用户可以快速下载需要的学术家族树图,而不用自己手动截图。

文件上传实现思路&代码片段

/**
 * 文件上传辅助函数
 */
function upload() {
    $('#fileinp').click();
}

/**
 * 文件上传功能
 */
function fileUpload() {
    let file = document.getElementById('fileinp').files[0];
    let reader = new FileReader();
    reader.readAsText(file, 'utf-8');
    reader.onload = function () {
        $(".input-area").val(reader.result);
        analyse();
    }
}
  • 实现思路:因为上传文件的表单控件比较难看,而且样式不方便修改,所以将该控件隐藏,并且通过给按钮绑定事件,通过按钮的点击事件触发表单的点击事件来实现文件上传。上传之后,通过 FileReader 这个类读取文件,并将文本写入输入框,之后,直接调用解析函数绘图。

成果展示

  • 多棵树并存
  • 点击节点可以显示技能或经历
  • 文件上传
  • 保存家族树图(每棵树对应一张图)

六、目录及使用说明

  ├── public   index.html
  ├── css
  │   ├── bootstrap.min.css 
  │   └── global.css 
  └── js
      ├── echarts.min.js  
      ├── global.js
      └── jquery-3.4.1.js
  • css目录中放的是index页面使用到的样式,包括了bootstrap和自己编写的一些全局样式。
  • js目录中放的是javascript文件,echarts.js帮助我们快速生成树状图,global.js负责字符串的解析和树状图的呈现,jquery-3.4.1.js让我们更方便的操作dom。
  • test目录中放的是测试的代码
  • 使用说明:index.html是主页面,用户直接双击文件夹中的index.html或右键选择浏览器打开就能运行我们的网页。

七、单元测试

  • 选用框架: mocha

简易教程

  1. 安装并配置 node.js, 具体可参照 https://blog.csdn.net/zjh_746140129/article/details/80460965?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-6.add_param_isCf&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-6.add_param_isCf
  2. (可选) 国内npm源速度较慢,可以配置淘宝镜像,具体可参照https://developer.aliyun.com/mirror/NPM?from=tnpm
  3. 如果前端项目没有使用npm构建,那么需要单独创建测试项目node init
  4. 全局安装mocha npm install --global mocha
  5. 将要测试的js拷贝到测试项目根目录,并创建 test 文件夹
  6. 在要测试的js文件中导出要测试的函数(比如要测试parse函数)
  7. 编写测试文件,可参照https://www.liaoxuefeng.com/wiki/1022910821149312/1101756368943712
  8. 在根目录输入mocha,运行测试

部分测试代码

describe('#global.js', () => {

    describe('异常情况', () => {
        it('导师信息异常', () => {
            assert.throws(() => {
                testJs.parse(`张三
2016级博士生:天一、王二、吴五、A
2015级硕士生:李四、王五、许六
2016级硕士生:刘一、李二、李三
2017级本科生:刘六、琪七

刘六:JAVA、数学建模

李二:字节跳动、京东云

王二: Python`)
            }, Error);
        });

利用 mocha 提供的describe 函数和 node.js 提供的 assert 进行单元测试,assert.throws代表期望抛出异常。运行mocha后,将会自动运行所有测试(由于使用了模板字符串,所以缩进有些混乱)

  • 运行结果

测试思路

  • 测试数据主要被分为了正常情况和异常情况,正常情况主要构造了单棵树和多棵数的测试数据,对于异常情况,因为这次的数据完全由用户输入,所以需要考虑的异常情况较多,因此针对各种格式错误构造了比较多的异常数据进行测试。例如输入不存在的数据,符号用了英文的符号,关键词不正确等异常。
  • 应对测试的***难:得益于全局的异常处理,对于没考虑到的异常也会被捕获并打印在绘图区,只是提示信息不够友好,测试人员可以根据该异常信息判断问题。

八、github记录

九、遇到的问题和解决方法

  • 问题一:css没写好没用好,页面布局没有达到想要的效果,不好看(虽然改完也不好看但是比一开始好),后来查文档,百度样式,搜索视频,参考其他页面的样式解决了这个问题。
  • 问题二:测试的时候发现,通过" "拼接的字符串可以通过测试,但是同样的文字使用模板字符串就无法通过测试,经过询问同学以及大量的日志调试后,发现是原本以为是空行的地方被 VSCode 自动加上了空格符进行缩进,导致解析不正确。最后删去多余的缩进后问题解决。这个小坑让我更深入的理解了 ES6 的模板字符串的相关特性,毕竟平时前端写的少,js这块的知识也是东缺一块西缺一块的。

十、评价队友

  • 值得学习的地方:我的队友就是大腿了,实力抱腿,他的代码熟练程度和学习能力是值得我学习的。
  • 需要改进的地方:我的队友要注重代码细节,才不会总有小问题。我需要多接触一些现代前端开发的知识,如三大框架,前端工程化等
posted @ 2020-10-11 13:35  DQBryant  阅读(319)  评论(2编辑  收藏  举报