點擊上方 前端Q,關注公眾號
回復加群,加入前端Q技術交流群
本文為讀者投稿,感謝時光大佬。
原文為:https://www.wolai.com/4RCFtUJ1gqnP5eTNCkxCkB
我們先來回顧幾個公知問題
自動化測試就是面向這些問題而生的。
接下來我們進入正題,向大家介紹前端自動化測試
前端自動化測試的種類共四類:
單元測試單元測試是最基礎的自動化測試,用來檢測項目當中的最小可測單元,例如工具函數、基礎組件等
集成測試在單元測試的基礎上,不同功能集成在一起,驗證整體功能
ui測試並不是只對ui設計效果的驗證,而是只對數據渲染、交互上的驗證
在vue或react這種前端框架下,延伸出一種組件測試,根據組件的粒度,其實應該屬於單元測試、或者集成測試的部分。
自動化測試金字塔介紹完自動化測試的種類,我們來簡單比較一下這四種測試
有下之上,測試用例的數量逐步減少、粒度變粗、驗證的功能變多變複雜。
同時受需求變化的影響變大,重複利率降低
同時編寫測試用例的時間變長 、執行的時間也響應變長
另一方面,由上至下,發先的bug數量逐漸變小。
所以,從發先bug數量/編寫測試用例時間&重複利用率的緯度上講,單元測試的收益最大,越向上收益越小。
這也是大部分項目中採用的自動化測試,是在單元測試這一層的原因。
滿足自動化測試的條件說了那麼多,哪什麼情況下,我們適合使用前端自動化測試呢?
這裡我總結了一些情況,實際上只需要滿足幾點就可以了
一些常見的測試工具單元測試(Unit Test)有 Jest, Mocha
端到端(E2E Test)Cypress.io、Nightwatch.js、Puppeteer、TestCafe
說了這麼多,其實應用的最廣泛的,收益相對來講最高的還是單元測試
所以後面我將具體給大家講一下,如何將單元測試融入到我們的開發當中
如何編寫單元測試我們是先開發,後補充單元測試呢?還是先編寫單元測試再開發呢?
相信大多數第一次,接觸這個問題的人可能都想我一樣,覺得是先開發後補充
但是實際上應當是先編寫單元測試,在開發代碼。這種模式成為測試驅動開發(TDD)
很簡單的道理,如果你寫的代碼邏輯有問題,那麼按照錯誤邏輯寫的單元測試,永遠不可能驗證出問題來。
我們應當圍繞功能設計來編寫我們的單元測試,測試內容對我們來講就是一個黑盒,我們只需要驗證他是否滿足我們的設計預期就好了,而無關內部細節。只有這樣,才能保證測試用例的穩定,支撐重構
測試驅動開發流程分節點開發,一邊開發一邊驗證,擴大測試通過範圍運行
單元測試步驟準備(Arrange)為測試做好設置。渲染組件/執行條件/準備數據
行動(Act)
對系統執行操作,例如點擊按鈕、觸發鉤子函數
假設現在我們要開發一個按鈕,
我們先來設計這個按鈕的功能
首先能接收自定義文字,能夠接收size設置不同尺寸,能夠觸發事件,然後還有禁用功能
接下來我們開始寫單元測試
// tests/button.spec.js
import Button from '@/components/Button.vue'
import { mount } from "@vue/test-utils"
const BUTTON_TEXT = '點擊'
describe('Button.vue', () => {
it('render text', () => {
const wrapper = mount(Button, {
slots: {
default: BUTTON_TEXT,
},
})
expect(wrapper.text()).toBe(BUTTON_TEXT)
})
it('size', () => {
const wrapper = mount(Button, {
propsData: {
size: 'small'
}
})
expect(wrapper.classes()).toContain('btn-small')
})
test('handle click', async () => {
const wrapper = mount(Button, {
slots: {
default: BUTTON_TEXT,
},
})
await wrapper.trigger('click')
expect(wrapper.emitted().click).toBeDefined()
})
test('handle disabled click', async () => {
const wrapper = mount(Button, {
slots: {
default: BUTTON_TEXT,
},
propsData: {
disabled: true
}
})
expect(wrapper.classes()).toContain('is-disabled')
await wrapper.trigger('click')
expect(wrapper.emitted().click).toBeUndefined()
})
})完成組件功能
<template>
<button
:class="[
'el-button',
size ? 'btn-' + size : '',
{
'is-disabled': disabled,
}
]"
@click="handleClick">
<span v-if="$slots.default"><slot></slot></span>
</button>
</template>
<script>
export default {
props:{
size:{
type:String,
required:false
},
disabled:{
type:Boolean,
default:false,
required:false
},
},
methods:{
handleClick(evt) {
!this.disabled && this.$emit('click', evt)
}
}
}
</script>
<style>
//省略樣式
</style>
總結在開發中引入前端自動化測試,可以幫我們帶來很多好處。但是同時不能忽視的一個問題,就是成本、無論是編寫自動測試的時間成本,平臺的搭建成本,項目成員學習自動化測試的成本。要考慮驗證的的內容是否有價值需要自動化測試,我們費勁心血寫的自動化測試是否足夠穩健,不會頻繁變更。
總之只有合適的才是最好的。