DevUI是一支兼具設計視角和工程視角的團隊,服務於華爲雲 DevCloud平臺和華爲內部數箇中後臺系統,服務於設計師和前端工程師。
官方網站: devui.design
Ng組件庫: ng-devui(歡迎Star)
官方交流:添加DevUI小助手(devui-official)
DevUIHelper插件:DevUIHelper-LSP(歡迎Star)
業務需求變化快、涉及大量的UI 和交互、大部分業務場景是在與後端交換並處理數據。以上幾點事實讓測試成爲前端領域讓人很是頭疼的問題,也成爲前端不寫單元測試的藉口。
html
當咱們面臨一個不太熟悉的領域或場景時,簡單可快速實施的內容更容易讓咱們邁出第一步。本文的目的正在於此,讓你二十分鐘以內能夠完成單元測試的spike 內容,以及將相關內容移植到項目代碼中。前端
本文包含三部份內容:git
(1)爲何要寫測試,包含了不少常見的關於測試的觀點、誤解和策略程序員
(2)如何書寫測試?經過spike 來看一個典型測試的構成github
(3)20 分鐘把單元測試集成到已有項目中chrome
前端業務因爲自身的特殊屬性,單元測試很差寫。這麼長時間以來沒寫測試,感受也沒什麼問題。另外,每一個迭代的業需求量那麼大,光搞業務開發都已經焦頭爛額了。之前我一直秉持這樣的觀念,因此就歷來沒有寫過單元測試。
segmentfault
注:文章後續提到的測試若是不註明前綴,都是指單元測試。單元測試的執行速度快,覆蓋範圍廣。按照測試金字塔原理,單元測試的覆蓋率應該達到100%!
後端
看過《重構》、《JavaScript測試驅動開發》和《Google軟件測試之道》這三本書後,我找到了不起不開始寫測試的理由:數組
(1)測試是活的文檔。代碼是給人讀的,相比於註釋,測試更容易讓人讀懂;
(2)測試有利於重構。有單元測試的代碼在功能擴展和重構時,操做成本更低;
(3)測試能提高代碼質量。一旦開始寫測試,你就會發現本身的代碼組織結構多麼混亂,會逼着本身從代碼的源頭設計來解決問題,寫出可測試的代碼,下降代碼圈複雜度。
前端工程師
關於代碼的圈複雜度,團隊裏的同事曾經寫過一篇文章來專門介紹,感興趣的能夠參考:https://juejin.im/post/684490...
另外關於圈複雜度分享一個很是amazing的小知識。Bob大叔說:理想的方法長度不該該超過四行代碼。沒錯,就是寫出《程序員的職業素養》一書的Bob大叔,這是一本你不論在什麼時間段看必定會有所收穫的書。若是你尚未讀過,牆裂推薦。
鑑於此,我下定決心要給本身的項目寫單元測試,而且已經隱約有了眉目,應該如何去寫。
上面扯了那麼一大堆,其實你們都明白。「道理我都懂,就是以爲很難如下手」。因此在開始以前,咱們必需要先回答兩個問題,也是大多數人遲遲不肯意開始書寫測試的緣由:
要達到或者接近100% 的單元測試覆蓋率,代碼量基本上要翻倍。好比說,知名的驗收測試工具FitNesse 擁有6.4 萬行代碼,其中2.8 萬行代碼是單元測試代碼(數據來自《程序員的職業素養》)。這是一個讓人望而生畏的比例,我也曾一度對「寫測試會給開發者帶來極大的成本」這個觀點深覺得然,直到我看到這樣一句話,在此拿出來跟你們分享:
有人會告訴你TDD 能減小缺陷,可是有成本,你會編寫比產品代碼多兩倍的測試代碼,因此會下降速度。這種假設認爲影響軟件開發的因素是打字速度,但這不是真的,實際上的影響因素是閱讀需求文檔、編寫文檔、開會、定位和修復bug。
這句話就不進行解讀了,你們細品。
也就是咱們在引子裏提到的那些問題,既然從上述角度來看,很是難以入手。那咱們不妨以另外兩個基本事實爲切入點,看看可否有所改善。
(1)每一個項目中都會有一些工具用來處理若干組件公用的業務邏輯,好比說特定時間日期的轉換等,這些方法一般分佈在普通的ts 文件或者service.ts 裏面
(2)Angular 項目中會用到大量的pipe,pipe 實際上就是一個處理輸入輸出且邏輯穩定的函數
看到這兩點,相信你的腦海中可能已經浮現出具體的函數名,咱們就從這部分代碼開始。
所謂的spike(中文可翻譯爲【輕輕地刺】),是指當咱們面臨一個不太熟悉的技術領域的時候,先拋開目前已有的東西,迅速從零開始創建一個demo,以考察咱們的方向是否可行。每一個人在平常工做中應該都有過運用spike 解決問題的經歷,尤爲是在進行帶有技術預演性質的工做時。只是可能不少人不知道該如何來描述這個過程。
回到正文,大多數團隊面臨的狀況多是,個人代碼目前運行良好(至少not bad),每一個迭代有大量的需求要作。團隊裏面一直沒有寫測試的傳統,也沒有人關心。要在這樣一個快速演進的項目中集成本身不太熟悉的技術領域,確實是一個麻煩事。所以,咱們先來作一個spike。用ng-cli 新建一個項目完成咱們對Angular 單元測試的探索。在spike 當中,咱們能夠拋開全部規範、設計層面的約束,只是爲了探索和驗證。
首先,咱們用ng-cli 建立一個新的項目,這個操做實在是再簡單不過了
ng new spike-test
而後
cd spike-test ng test
就像上面那樣,咱們已經完成了一個最簡單的包含單元測試的項目,這個過程大概只花了你3分鐘的時間?如今咱們把這個項目拆開看看,以便把必要的信息提取出來集成到咱們已有的項目中。
主要來看看app.component.spec.ts 這個文件
從這個測試文件中,咱們能夠看到,要完成一個測試,首先要引入一些跟測試相關的包和被測試的組件(或是服務、管道甚至普通的ts 文件)。
一個測試套件(describe)裏面會包含若干個should,也就是測試應該驗證的行爲,在這個例子中就是如下三點:app 應該被建立、title 應該是spike-test、title 應該配渲染在h1 tag 裏。
除了這個,還須要用到不少相關的配置文件。可是總的來說,仍是很是簡單。既然如此,那麼就開始動手吧,在已有的項目中集成測試用例。
在這個環節中遇到的全部問題,好比說文件位置放在哪裏,文件的內容是什麼等,均可以參考咱們上一小節已經作好的spike 項目來進行配置。
(1)確保根目錄下有karma.conf.js 配置文件
(2)確保src下有test.ts 文件
(3)確保你的spec.ts 文件沒有被tsconfig 忽略,主要檢查tsconfig 文件中的include 和exclude 配置
(4)確保有安裝如下幾個依賴,若是沒有,先所有安裝上
"karma": "^5.2.1", "karma-chrome-launcher": "^3.1.0", "karma-coverage-istanbul-reporter": "^3.0.3", "karma-jasmine": "^4.0.1", "karma-jasmine-html-reporter": "^1.5.4",
在開始寫以前,咱們先梳理下寫測試用例的基本步驟:
(1)先經過手寫列表記錄下你想要測試的行爲,也就是上面spike 中的若干個should
(2)按照上述列表書寫測試用例
以上依賴和配置弄好之後,咱們就能夠開始嘗試在已有的項目中編寫測試用例,假設咱們有一個將字節(Byte)轉換爲經常使用大小表示的方法(好比KB、MB、GB),方法的代碼以下:
如上所述,咱們先開始準備測試行爲列表:
而後開始爲這個公共方法書寫測試代碼,首先新建一個測試文件test.spec.ts,在文件中引入這個方法
import { transferSize } from './common-method';
接着添加你的測試套件和若干個should
describe('TransferSize Method Of Util', () => { it(`should return '--' when the input is less than zero`, () => { expect(transferSize(-1)).toEqual({ sizevalue: '--', sizeunit: '' }); }); it(`should return '--' when the input is not number`, () => { expect(transferSize('haha')).toEqual({ sizevalue: '--', sizeunit: '' }); }); it(`should return 'xB' when the input is less than 100`, () => { expect(transferSize(0)).toEqual({ sizevalue: '0', sizeunit: 'B' }) }); it(`should return 'xMB' when the input is more than 100`, () => { expect(transferSize(100)).toEqual({ sizevalue: '0.1', sizeunit: 'KB' }) }); it(`should return 'xGB' when the input is more than 100000`, () => { expect(transferSize(100000)).toEqual({ sizevalue: '0.1', sizeunit: 'MB' }) }); it(`should return 'xGB' when the input is more than 100000000`, () => { expect(transferSize(100000000)).toEqual({ sizevalue: '0.1', sizeunit: 'GB' }) }); });
寫完了,運行ng test,成了!
一個最簡單的單元測試用例已經被咱們集成進了已有的項目中。
若是你還想看項目中每一個文件的代碼測試覆蓋率,能夠運行這個命令:ng test --code-coverage,固然記得在你的Karma.conf.js 中配置coverage 文件夾的路徑
這樣配置完成之後,每次你執行完上述命令,一個更詳細的結果會產生了項目根目錄下的coverage 文件夾中,打開文件夾中的index.html 文件能夠看到每一個文件的測試覆蓋率及未覆蓋代碼。
爲了達到快速實施的目的,本文只是將必要的部分串聯起來組成了一個可操做的最小化demo,還有許多關於測試的問題沒有解答,好比各類測試覆蓋度的計算方式,如何利用mock & stub 進行接口交互業務測試,如何針對像DevUI 這種組件庫場景下進行測試。
關於上面提到的全部未解答問題,我們下期見。
咱們是DevUI團隊,歡迎來這裏和咱們一塊兒打造優雅高效的人機設計/研發體系。招聘郵箱:muyang2@huawei.com。
文/DevUI 少東
往期文章推薦