第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、評價隊友

  * 值得學習的地方:期間一直勸我不要放棄,要堅持
  * 需要改進的地方:頁面設計得不好看


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM