vue的自動化測試


大廠視野

 

1.流量大

 

  • 性能優化

 

2.項目復雜

 

  • 源碼

 

3.持續迭代

 

4.項目穩定運行

 

  • 自動化測試

 

  • 需求評審

 

  • 開發

 

  • 測試(人點)(可以使用自動化測試完成一部分)

 

  • 上線

 

5.為什么要寫測試呢

 

  • 測試代碼可讀性好,易於維護
  • 替代了測試的部分工作,無形中完成了一部分任務

 

准備

 

1.了解自動化測試

 

2.jest

 

3.cypress

 

4.端對端和自動化

 

測試分類

 

常⻅見的開發流程⾥里里,都有測試⼈人員,這種我們成為⿊黑盒測試,

 

測試⼈人員不不管內部實現機制,只看最外層的輸⼊入輸出,⽐比如你寫⼀一個加法的⻚頁⾯面,會設計 N個case,測試加法的正確性,這種代碼⾥里里,我們稱之為E2E測試

 

更更負責⼀一些的,我們稱之為集成測試,就是集合多個測試過的單元⼀一起測試

 

還有⼀一種測試叫做⽩白盒測試,我們針對⼀一些內部機制的核⼼心邏輯 使⽤用代碼 進⾏行行編寫 我們稱之為單元測試

 

這仨都是我們前端開發⼈人員進階必備的技能!

 

我們其實⽇日常使⽤用 console,算是測試的雛形吧,console.log(add(1,2) == 3)

 

測試的好處

 

組件的單元測試有很多好處:

 

  • 提供描述組件⾏行行為的⽂文檔
  • 節省⼿手動測試的時間
  • 減少研發新特性時產⽣生的 bug
  • 改進設計
  • 促進重構

 

⾃自動化測試使得⼤大團隊中的開發者可以維護復雜的基礎代碼。讓你改代碼不不再⼩小⼼心翼翼

 

測試梯圖

 

我們先來創建一個vue項目

 

vue項目創建后面選擇jest和cypress

 

裝好了以后有個test目錄,下有兩個目錄,unit和e2e,unit是單測,e2e是端對端

 

npm run test:unit 就可以進行測試了

 

單元測試

 

單元測試(unit testing),是指對軟件中的最⼩小可測試單元進⾏行行檢查和驗證。例如一個函數。

單測針對組件 或者函數 或者模塊(開發人員知道具體邏輯)

 

在vue中,推薦⽤用 Mocha+chai 或者jest,咱們使⽤用 jest演示,語法基本⼀一致

 

😊寫一個demo

 

在src建立utils.js,寫個add函數導出

 

export function add(x,y) {
    return x + y
}

 

在tests下的unit下的example.spec.js中修改(當然也可以新建一個*.spec.js,固定格式的文件)

 

// import { shallowMount } from '@vue/test-utils'
// import HelloWorld from '@/components/HelloWorld.vue'

// describe('HelloWorld.vue', () => {
//   it('renders props.msg when passed', () => {
//     const msg = 'new message'
//     const wrapper = shallowMount(HelloWorld, {
//       propsData: { msg }
//     })
//     expect(wrapper.text()).toMatch(msg)
//   })
// })

import { add } from '@/utils.js'
describe('測試加法函數',()=>{
  //測試代碼可讀性最好
  //分組
  it('一個具體的功能測試,測測試數字相加',()=>{
    expect( add(1,2) ).toBe(3)
  })
  it('一個具體的功能測試,測測試數字和字符串相加',()=>{
    expect( add('a',2) ).toBe('a2')
  })
  it('一個具體的功能測試,測測試數字字符串相加',()=>{
    expect( add('1',2) ).toBe(3)
  })
})

 

npm run test:unit 后

 

add測試結果測試結果為失敗(不通過)

 

這個案例我們就用到了4個api

 

api介紹

 

  • describe : 定義⼀一個測試套件
  • it :定義⼀一個測試⽤用例例
  • expect :斷⾔言的判斷條件
  • toBe :斷⾔言的⽐比較結果

 

測試vue組件

 

components下新建KaiKeBa.vue

 

<template>
    <div>
        <span>{{ msg }}</span>
        <span>{{ msg1 }}</span>
        <button class="btn" @click="changeMsg">點我</button>
    </div>
</template>

<script>
export default {
    data(){
        return {
            msg: "vue test",
            msg1: '你好'
        }
    },
    created() {
        this.msg = 'aftermounted'
    },
    mounted() {
        this.msg1 = '開課吧'
    },
    methods: {
        changeMsg(){
            this.msg = 'click over'
        }
    },
}
</script>

 

views目錄下的home組件中引入

 

<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png">
    <KaiKeBa></KaiKeBa>
  </div>
</template>

<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'
import KaiKeBa from '@/components/KaiKeBa.vue'

export default {
  name: 'home',
  components: {
    KaiKeBa,
    HelloWorld
  }
}
</script>

 

在tests目錄下的unit目錄下建立kaikeba.spec.js

 

import Vue from 'vue'
import KaiKeBaComp from '@/components/KaiKeBa.vue'
import { mount } from '@vue/test-utils'

describe('測試KaiKeBa組件',() => {
    it('測試初始化的data',() => {
        expect( KaiKeBaComp.data().msg ).toBe('vue test')
    })
    //created和mounted里數據測試都是一樣的
    it('測試新建完畢后,create生命周期后的數據',() => {//created
        let vm = new Vue(KaiKeBaComp).$mount()
        expect(vm.msg).toBe('aftermounted')
    })
    it('測試新建完畢后,create生命周期后的數據',() => {//mounted
        let vm = new Vue(KaiKeBaComp).$mount()
        expect(vm.msg1).toBe('開課吧')
    })
    //點擊事件測試
    it('測試點擊后,msg的改變',() => {
        // $mount處理不了用戶交互,所以我們要用到vue官方推薦的@vue/test-utils
        let wrapper = mount(KaiKeBaComp)
        expect( wrapper.vm.msg ).toBe('aftermounted')
        //點擊一下
        wrapper.find('.btn').trigger('click')
        expect( wrapper.vm.msg ).toBe('click over')
    })
})

 

如果測試用戶交互的話,需要用到官方推薦的@vue/test-utils,執行cnpm i @vue/test-utils --save,相關文檔在vue官網

 

在 @vue/test-utils 中引入mount替代vue的$mount的是因為$mount的是虛擬的,存在虛擬內存中,處理不了dom,所以用mount(對不對我不知道,這句話僅供參考)

 

測試覆蓋率

 

jest⾃自帶覆蓋率,如果⽤用的 mocha,需要使⽤用 istanbul來統計覆蓋率

 

package.json⾥里里修改 jest配置

 

jest: {
    "collectCoverage": true,
    "collectCoverageFrom": ["src/**/*.{js,vue}"],
  }

 

倘若有個jest.config.js那么就在 moduleFileExtensions 上一行加入,這個文件是對jest的配置

 

"collectCoverage": true,
"collectCoverageFrom": ["src/**/*.{js,vue}"],

 

在跑一下npm run test:unit

 

測試覆蓋率

 

生成的報告文件在coverage目錄下,打開可以看到這么個鬼東西

 

測試報告我們的測試報告

 

這個測試報告可以很精確的看到我們哪些沒測試,哪些測試了,我在KaiKeBa里加點東西不測試,來看看結果

 

新的測試報告

 

藍色的我們可以點進去的

 

詳細測試結果

 

指出了沒有測到的地方,判斷了newData是否等於1,顯然不等於的

 

我們可以給他測試下,要這么寫,給newData賦值

 

it('測試點擊后,newData == "1"的結果',() => {
        // $mount處理不了用戶交互,所以我們要用到vue官方推薦的@vue/test-utils
        let wrapper = mount(KaiKeBaComp)
        wrapper.vm.newData = '1'
        //點擊一下
        wrapper.find('.btn').trigger('click')
        expect( wrapper.vm.msg ).toBe('click false')
    })

 

修改后的測試報告

 

如何測試不通過就阻止代碼git提交

 

安裝husky:cnpm i husky --save

 

配置husky,在package.json

 

"husky": {
    "hooks": {
      "pre-commit": "npm test",
      "pre-push": "npm test",
      "...": "..."
    }
  }

 

當然這是文檔的,我們要按我們所需的改成

 

"husky": {
    "hooks": {
      "pre-commit": "npm run test:unit"
    }
  }

 

代表再提交(commit)前先執行npm run test:unit

 

🐱‍🚀驗證:

 

修改測試代碼文件kaikeba.spec.js

 

 

it('測試新建完畢后,create生命周期后的數據',() => {//created
        let vm = new Vue(KaiKeBaComp).$mount()
        expect(vm.msg).toBe('aftermounted')
    })

 

改為

 

it('測試新建完畢后,create生命周期后的數據',() => {//created
        let vm = new Vue(KaiKeBaComp).$mount()
        expect(vm.msg).toBe('aftermounted1')
    })

 

這樣測試肯定是不通過的

 

測試不通過

 

這時,我們來提交代碼,add后再commit

 

提交被終止如圖:提交被終止

 

那么我們再將測試文件改回來,讓測試可以通過

 

提交成功

 

如圖:測試通過,代碼也commit提交了

 

E2E測試

 

e2e針對應用,站在測試人員的角度,沒有什么mount 加載,只有按鈕 頁面,輸入框,文本等

 

借⽤瀏覽器器的能力,站在⽤戶測試⼈員的角度,輸⼊框,點擊按鈕等,完全模擬用戶,這個和具體的框架關系不大,完全模擬瀏覽器行為

 

😒將views下的Home組件的

 

<HelloWorld msg="Welcome to Your Vue.js App"></HelloWorld>

 

代碼恢復

 

😒看看tests目錄下e2e目錄下的spec下的test.js,有這么一段

 

// https://docs.cypress.io/api/introduction/api.html

describe('My First Test', () => {
  it('Visits the app root url', () => {
    cy.visit('/')
    cy.contains('h1', 'Welcome to Your Vue.js App')
  })
})

 

這是測試代碼,如果我們不做前面的恢復操作的話,測試肯定是不通過的

 

😒執行npm run test:e2e,進行測試

 

項目會啟動,並且會彈出一個有ok的彈窗,我們直接確定,還會有測試文件的js,選擇對應的測試文件點進去

 

e2e測試通過

 

這樣就已經測試通過了

 

😒再來測試一個about頁

 

// https://docs.cypress.io/api/introduction/api.html

describe('My First Test', () => {
  it('Visits the app root url', () => {
    //訪問根目錄
    cy.visit('/')
    cy.contains('h1', 'Welcome to Your Vue.js App')
  })
  it('測試about頁', () => {
    //訪問about
    cy.visit('about')
    cy.contains('h1', 'This is an about page')
  })
})

 

結果是這個樣子

 

后測的about

 

后測的about,就最后打開了about頁,也停留在了about頁面

 

這些都是頁面某個元素的文本的測試,那么我們再來個交互試試,在我們的KaiKeBa組件上有個點擊事件,我們來試試

 

// https://docs.cypress.io/api/introduction/api.html

describe('My First Test', () => {
  it('Visits the app root url', () => {
    //訪問根目錄
    cy.visit('/')
    cy.contains('h1', 'Welcome to Your Vue.js App')
  })
  it('測試about頁', () => {
    //訪問about
    cy.visit('about')
    cy.contains('h1', 'This is an about page')
  })
  it('KaiKeBa組件',() => {
    //訪問根目錄
    cy.visit('/')
    cy.contains('#msg','aftermounted')
    cy.get('button').click()//點擊button元素
    cy.contains('#msg','click over')
  })
})

 

點擊事件測試

 

左邊那一條條可以點擊,點擊不同的項,也會進入不同的事件狀態,例如我點了CONTAINS,文本變成了click over

 

題外話:測試頁面前后差異,或者兩個頁面的差異可以用page-monitor;地址: https://github.com/fouber/page-monitor

 

如何測試node?


免責聲明!

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



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