Node.js 單元測試:workflow
Talk is cheap, show me the code!
是否還記得小明在《 Node.js 單元測試之我要寫測試》里引用的這句話么,不過引用了之后,小明就像跑路了一般再也沒見其 code……其實呀,不知道大家有沒有關注最近比較火 minggeJs, 稍微聯想下你就知道小明最近在忙啥了 O(∩_∩)O~~
雖說小明現在還寫不出 minggeJs 這樣的前端庫,不過,小明想說的是: 當你準備開源一個庫的時候,一定要寫單元測試;當你要使用一個開源庫的時候,單元測試的覆蓋率是衡量質量的最重要標準之一 。
好了,扯了這么多閑話之后,明哥(不對,是小明……)接下來介紹一下在項目里單元測試整個流程是如何的。
Node.js 專屬之 npm scripts
起初,小明將 Mocha 和 istanbul 裝在全局命令下,然后每個項目都使用全局的命令,后來發現多人合作時會因為版本不一致而報錯,因此果斷將 Mocha 之類的裝在項目的 node_modules/ 下:
npm install mocha istanbul --save-dev
然后只需要執行下面兩條命令即可:
# 執行單測 ./node_modules/.bin/mocha test/*.test.js --timeout 20000 # 收集覆蓋率報告 ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha -- -u exports --reporter spec --timeout 20000
然而每次都執行這么長的命令讓隔壁(座位)的老王實在看不下去了,于是就告訴小明 npm scripts 的用法。只需要在 package.json 里定義幾個命令即可:
"scripts": { "test": "./node_modules/.bin/mocha 'test/*.test.js' --timeout 20000", "cov": "./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha -- -u exports 'test/*.test.js' --timeout 20000" }
如此之后,每次寫完代碼,小明只需要執行 npm run test/cov 即可,省事了很多。
不知道諸位有沒有注意到,小明在 'test/*.test.js' 上故意加了一個引號,這一點也是小明被坑了之后才發現的:執行 shell 命令時,如果參數中包含如 test/*.test.js 這種 glob 模式,對應的 shell 會自動解析掉,但是不同的 shell 對 glob 的實現又不一致,因此就會出現匹配文件出錯的問題,當加了引號之后,shell 會把參數原封不動的交給 Mocha(或者其他工具)來解析,這樣才能保持不同 shell 的一致性。
當然, npm scripts 還有很多對于 Node.js 開發者很便利的功能,請參閱文末的相關鏈接。
構建利器 makefile
隨著代碼的積累,小明寫的單測也越來越多,有時候可能只需要運行某一個測試文件,所以小明希望能通過命令行參數將需要測試的單個文件傳進去,這時候 npm scripts 就顯得捉襟見肘了。于是小明繼續秉持著「有問題找老王」的原則,老王毫不猶豫的給小明推薦了 makefile .
關于 makefile 的介紹,網上有很多的資料,小明的簡單理解就是: makefile 就是將某個流程(如編譯、打包、構建等)包含的所有相關命令集成到一個 make 命令下,極大的方便開發者。具體到目前的場景,可以參照如下的示例:
test := './test/*.test.js' timeout := 20000 mocha := ./node_modules/.bin/mocha istanbul := ./node_modules/.bin/istanbul coverageMocha := ./node_modules/.bin/_mocha test: echo '開始運行單測' $(mocha) --timeout $(timeout) $(test) echo '單測運行結束' cov: $(istanbul) cover $(coverageMocha) -- -u exports $(test) --timeout $(timeout) # 區分命令和文件名稱 .PHONY: test
在項目里定義了如上的 makefile 文件后,只需要執行 make test 就可以跑單元測試了,并且上面提到的傳參數的問題也可以迎刃而解: make test test=test/util.test.js . 相對于 npm scripts , makefile 借助 shell 腳本的能力要強大靈活很多,然而一個不太好的消息是:windows 并不支持 makefile ……
持續集成
在經過了上面的這些步驟之后,小明在本地已經可以完美的執行單元測試了,然而在跟小伙伴們合作的過程中,小明發現有的同學并不是很關注這個事情,單元測試沒跑通過就將代碼 push 到了遠程倉庫,這時候就需要其他同學來幫忙擦屁股,很是不方便。
于是,老王就告訴了小明持續集成這個東西,所謂持續集成,簡單來講就是:在代碼 push 之后,對代碼進行一系列的構建,比如 lint 檢測、單元測試、部署等,借此提高代碼的質量以及多人合作開發效率。而在 Node.js 領域,這方面比較優秀的工具就是 travis-ci 了,小明也順便體驗了一下 travis-ci, 按照其三步走的接入流程的確是非常之方便。
然而,小明平時開發的倉庫大部分都是托管在內部的,沒法使用面向 GitHub 的 travis-ci, 這一次小明決定不再去問老王了,程序員嘛,造輪子的功能還是要有的。于是,在一個多月的開發后,小明基于內部的其他服務做出了一個八九不離十的持續集成系統,名曰 UITest-ci:
這個系統可以運行單測、執行 lint、可以生成覆蓋率報表、可以通知開發者集成結果、同時提供徽章服務,近乎完美。之后有時間了再詳細介紹這個系統的設計和實現吧 :)
來自: http://taobaofed.org/blog/2015/12/29/nodejs-unit-tests-workflow/