第4次作业-结对编程之实验室程序实现

这个作业属于哪个课程 https://edu.cnblogs.com/campus/fzu/SE2020
这个作业要求在哪里 https://edu.cnblogs.com/campus/fzu/SE2020/homework/11277
这个作业的目标 结对编程,学习前端,单元测试,github
学号 031802513-031802516

团队成员

学号 姓名
031802513 黄展
031802516 兰杰

1、开头:

标题 链接
结对同学博客链接 https://www.cnblogs.com/jieblue/
本作业博客的连接 https://www.cnblogs.com/qewpqewp
仓库地址 https://github.com/jieblue/031802513-031802516

2、具体分工:

 031802513完成js部分和vue的框架构建,单元测试框架
 031802516完成html部分,完善单元测试用例,美化页面

3、PSP表格

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

4、解题思路描述与设计实现说明

  • 实现思路
    0、此项目用Vue+element-ui实现,测试模块为jest+vue/test-utils
    1、将文本处理,生成树结构
    2、树结构:{name:"张三",children:[{name:"2018级研究生",children:[{name:"李四",detail:"java"},{name:"王五",}]},{name:"2019级研究生",children:[{name:"赵六"},{name:"陈7"}]}]}
    (每个节点有name、detail、children字段)
    3、树合并算法,遍历每个树的叶节点,判断是否有某根节点的name=叶节点的name,如果有,就将此根节点替换成此叶节点
    4、将此树结构传入Tree组件,Tree组件递归形成图形树

  • 数据流图

  • 代码片段
    树结构生成算法:将输入的文本逐行读取,每行出现“导师:”时,储存此导师名字,此时进入学员录入模式,之后的每一行都是该导师学员的信息。当读取到空行时,结束此导师的录入模式,重复此过程直到读取到某非空行且不处于学员录入模式时,则开始录入每个学员的具体信息。

initData() {
      var nowTeacher = "";//当前教师
      this.lines = this.text.split("\n");//以行分割
      this.lines.forEach((item) => {//遍历每一行
        if (item.includes("导师:")) {//判断是导师
          var temp = item.split(":");
          nowTeacher = temp[1];//开始录入此导师的子节点的标志
          this.teacher.push({ name: temp[1], children: [], extend: false ,image_url : require("../assets/head.jpg")});
        } else if (item === "") {//导师后出现空行
          nowTeacher = "";//停止导师录入子节点
        } else if (nowTeacher !== "") {//导师的子节点
          var temp1 = item.split(":");
          var students = temp1[1].split("、");
          this.teacher.filter((item) => {
            if (item.name === nowTeacher) {
              var children = [];
              students.forEach((s) => {
                children.push({ name: s ,    image_url : require("../assets/head.jpg")});
              });
              item.children.push({
                name: temp1[0],
                children: children,
                extend: false,
            
              });
            }
          });
        } else {//判断是学生的具体信息
          var temp2 = item.split(":");//temp2[0]学生姓名,temp2[1]学生详情

          this.teacher.forEach((teacher) => {

             if (teacher.name === temp2[0]) {
                  teacher.detail = temp2[1];

                }
            teacher.children.forEach((grade) => {
              grade.children.forEach((item) => {
                if (item.name === temp2[0]) {
                  item.detail = temp2[1];

                  return;
                }
              });
            });
          });
        }
      });
    },
  },

五、附加特点设计与展示

设计的创意独到之处,这个设计的意义:

  • 拖拽功能、结点收缩展开、文件上传
  • 意义:当成员信息较多时,拖拽和结点收缩展开可以使得信息查看更便利,不会占据太多空间,文件上传可能没啥意义,后期可改成数据库读取

实现思路:

  • 1、拖拽:当模块触发鼠标左键按下事件后,监听鼠标移动事件,将模块的位置加上鼠标偏移量,当鼠标左键抬起后停止监听。
  • 2、结点收缩展开,由于树结点是递归形成,每个结点的树结构含有一个extend字段,当此字段为true时,此结点显示,反之隐藏
  • 3、文件上传(略)

代码(拖拽功能):

 directives: {
    //拖拽功能
    drag: {
      // 指令的定义
      bind: function (el) {
        let oDiv = el; // 获取当前元素
        oDiv.onmousedown = (e) => {
          // 算出鼠标相对元素的位置
          let disX = e.clientX - oDiv.offsetLeft;
          let disY = e.clientY - oDiv.offsetTop;

          document.onmousemove = (e) => {
            // 用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
            let left = e.clientX - disX;
            let top = e.clientY - disY;

            oDiv.style.left = left + "px";
            oDiv.style.top = top + "px";
          };

          document.onmouseup = () => {
            document.onmousemove = null;
            document.onmouseup = null;
          };
        };
      },
    },
  },

使用方法:在标签里面加个 -drag <div v-drag>

成果展示

六、在博客中给出目录说明和使用说明

目录组织:

  ```

  ├── public   index.html默认位置
  ├── src
  │   ├── assets 资源文件夹
  │   ├── components 组件
  │   ├── router 路由配置
  │   └── views  主页面
  └── test
      └── unit  单元测试文件

  ```

运行方式:

  • 1 安装node.js https://nodejs.org/zh-cn/ (12.9.0)
  • 2 下载完可检查在windows任务命令行里输入node -v
  • 3 使用淘宝NPM镜像源下载比较快    命令:npm install -g cnpm --registry=https://registry.npm.taobao.org
  • 4 clone仓库
  • 5 cd 031802513-031802516
  • 6 npm install 安装框架
  • 7 npm run serve 运行
  • 8 访问 http://localhost:8080/

七、单元测试

  • 测试工具:jest+vue/test-utils

  • 安装方式:在构建vue项目的时候引入jest,之后在项目中npm install @vue/test-utils 安装vue/test-utils模块

  • 在tests/unit文件夹内创建 xx.spec.js文件,用来写测试用例

    简易教程(测试用例文件写法):
    1、import { shallowMount } from '@vue/test-utils'  //引入 vue/test-utils的 shallowMount函数来挂载需要测试的组件
    2、例子
    
import Vue from 'vue'
import index from '@/components/index'
import { shallowMount } from '@vue/test-utils'
describe('index页面测试', () => {
       //shallowMount挂载测试组件(此函数不生成子组件,mount生成子组件)
  const wrapper = shallowMount(index)
      //断言格式
  it('验证是否渲染了页面按钮', () => {
    expect(button.text()).toEqual('生成')
  })
  3、   同等性断言 Equality Asserts
              expect(sth).toEqual(value)
              expect(sth).not.toEqual(value)
        比较性断言 Comparison Asserts
              expect(sth).toBeGreaterThan(number)
              expect(sth).toBeLessThanOrEqual(number)
        类型性断言 Type Asserts
              expect(sth).toBeInstanceOf(Class)
        条件性测试 Condition Test
              expect(sth).toBeTruthy()
              expect(sth).toBeFalsy()
              expect(sth).toBeDefined()
  4、运行npm run test:unit

  • 单元测试代码
    index.vue 测试
  const button = wrapper.findAllComponents({ name: 'el-button' }).at(1)
  it('验证是否渲染了页面按钮', () => {
    expect(button.text()).toEqual('生成')
  })
  wrapper.vm.text = "导师:张三"
  button.trigger('click');
  it('测试按钮是否能点击', () => {
    expect(wrapper.vm.teacher[0].name).toEqual("张三")
  })
  it('测试树生成算法', () => {
    wrapper.vm.text = `
导师:张三
2016级博士生:天一、王二、吴五
2015级硕士生:李四、王五、许六
2016级硕士生:刘一、李二、李三
2017级本科生:刘六、琪七、司四

刘六:JAVA、数学建模

李二:字节跳动、京东云 
          `
    
      button.trigger('click');
      var teacher = wrapper.vm.teacher[0]
    expect(teacher.children[0].name).toEqual("2016级博士生")
    expect(teacher.children[1].children[2].name).toEqual("许六")
    expect(teacher.children[3].children[0].detail).toEqual("JAVA、数学建模")
  })
    it('测试复杂树生成算法,当一个导师是另一个导师的学员的情况', () => {
      wrapper.vm.text = `
导师:张三
2016级博士生:天一、王二、吴五
2015级硕士生:李四、王五、许六
2016级硕士生:刘一、李二、李三
2017级本科生:刘六、琪七、司四

导师:王九
2013级博士生:刘久、张三、周七
2012级硕士生:李一、王八、许四

刘六:JAVA、数学建模

李二:字节跳动、京东云
              `
          button.trigger('click');
          var teacher = wrapper.vm.teacher[0]
      expect(teacher.children[0].name).toEqual("2013级博士生")
      expect(teacher.children[0].children[1].name).toEqual("张三")
      expect(teacher.children[0].children[1].children[1].children[2].name).toEqual("许六")
    })

tree.vue测试

it('验证树根组件是否正确渲染', () => {
      expect(wrapper.find('.name').text()).toEqual('张三')
    })
    it('验证树结点数量', () => {
      expect(wrapper.findAllComponents(tree).length).toBe(7)
    })

    it('验证子节点组件是否正确渲染', () => {
      expect(wrapper.findAllComponents(tree).at(1).findAllComponents(tree).at(1).find(".name").text()).toEqual('李四')
    })
    const button=wrapper.findComponent({name:'el-button'})
    it('验证学生查看详情按钮', () => {
      expect(button.text()).toEqual('查看详情')
      
      wrapper.vm.showDetail({name:"李四",detail:"haha"})
      expect(wrapper.vm.detail).toEqual("haha");
    })
  • 测试数据思路,先测试单棵树的情况,就类似给出的测试数据,然后测试当一个导师是另一个导师的学员的情况,最终结果的树会合并。测试人员可能会输入一个不符合命名标准的数据,此代码并没有判断错误命名的能力。

8、github 签入记录

9、遇到的代码模块异常或结对困难及解决方法

  最大的困难是单元测试模块的引入。刚开始引入的时候,所有的测试用例所指向的组件都出现js代码错误,最开始的报错是"forEach"函数不存在。经多次查找资料,发现是因为jest版本过低,js编码不支持es6版本,而forEach是es6新引入的特性。
  于是手动修改package.json升级模块,但由于涉及到的模块特别多,每个模块的版本又都互相限制,因此会产生各种不支持。
  后来尝试了重新构建项目,引入Karma+Mocha模块单元测试,但与vue/test-utils不太兼容,对于element-ui无法测试。
  最终将vue-cli升级到vue-cli 3版本,并重构项目,才得以成功进行单元测试。
  期间非常绝望,花了两天时间来解决这个问题,重构项目好几次,几乎快要放弃了,甚至去询问唯一认识会vue的学姐,结果告诉我她不会写测试。
  收获:还是趁早放弃为好,下次可没有那么幸运了。不能丢了西瓜捡芝麻。

10、评价队友

  * 值得学习的地方:期间一直劝我不要放弃,要坚持
  * 需要改进的地方:页面设计得不好看
posted @ 2020-10-11 00:42  qewpqewp  阅读(489)  评论(2编辑  收藏  举报