單元測試就是測試最小單元(一個方法,一個組件)。git
雖然你們都已經回答過無數次這個問題了,可是那並不表明我確實理解了。github
我之前也沒有寫過單元測試,這也是爲何要來記錄這篇文章的緣由。npm
對於寫單元測試,我我的的直觀感觸是能夠促使本身編寫更「純」的函數或方法。這其實對於代碼的閱讀、維護、重構等都帶來了優惠。你能夠更加明確這個函數的做用,至少會千方百計讓本身的函數所影響的範圍進行縮減、可控。json
再者說,對於 CI/CD,單元測試又是很是有必要的一個環節。bash
我也相應的搜索了一些網絡上小夥伴們的解答,你們無外乎都是在圍繞着可閱、可用、易於重構、自我提高這些方面在闡述,總之寫單元測試是一件好的事情,若是你有能力有時間,那麼請嘗試一下而且持續的寫下去吧。網絡
通過一些查閱,mocha + chai 彷彿是一個比較廣泛的選擇。框架
mocha 是一個測試框架,它對異步代碼的追蹤測試頗有自信。異步
chain 是一個斷言庫。函數
此外還有一個 jest,它是一個大而全的測試框架,它使用內置的 matchers 斷言。工具
# 新建一個文件夾 mkdir mocha-chai # 進入文件 cd mocha-chai # 初始化 npm init -y # 安裝 yarn add mocha chai
接下來準備一個源碼文件 index.js
和 測試文件 index.spec.js
。
// index.js module.exports.getAbs = (x, y) => { return Math.abs(x - y) }
爲何必須是 .spec.js
?我去查了一下,結果以下:
約定俗成的術語。
Unit Testing Specification
(單元測試基準)的縮寫,不少框架默認回去找這些後綴的文件。
官方也給出一段相關的內容,不太肯定是否還有其餘處。
Test files can be specified usingspec
, e.g.,"spec": "test/**/*.spec.js"
.
// index.spec.js const assert = require('chai').assert const getAbs = require('./index').getAbs describe('to test getAbs()', () => { it('should return 1 when the value is 1,2', () => { assert.equal(getAbs(1, 2), 1, 'getAbs(1,2) equal 1') }) it('should return 1 when the value is 2,1', () => { assert.equal(getAbs(2, 1), 1, 'getAbs(2,1) equal 1') }) it('should return 0 when the value is 1,1', () => { assert.equal(getAbs(1, 1), 0, 'getAbs(1,1) equal 0') }) })
主要是 test
命令:
"scripts": { "test": "mocha index.spec.js" },
執行:
yarn test
yarn run v1.21.1 $ mocha index.spec.js to test getAbs() √ should return 1 when the value is 1,2 √ should return 1 when the value is 2,1 √ should return 0 when the value is 1,1 3 passing (8ms) Done in 0.46s.
如今,在 index.spec.js 文件中追加一個 it()
:
it('should return 0 when the value is not present', () => { assert.equal(getAbs(), 0, 'getAbs() equal 0') })
以後再次執行:
yarn test
yarn run v1.21.1 $ mocha index.spec.js to test getAbs() √ should return 1 when the value is 1,2 √ should return 1 when the value is 2,1 √ should return 0 when the value is 1,1 1) should return 0 when the value is not present 3 passing (18ms) 1 failing 1) to test getAbs() should return 0 when the value is not present: getAbs() equal 0 + expected - actual -NaN +0 at Context.<anonymous> (index.spec.js:15:12) at processImmediate (internal/timers.js:439:21) error Command failed with exit code 1. info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
總之就是未獲得預期的值得意思,很明顯這是由於沒有傳遞參數致使的。也就是說在不給函數傳遞參數的時候,函數的行爲有些不符合預期的效果。
因此稍做修改再來一次。
修改 index.js:
// index.js module.exports.getAbs = (x = 0, y = 0) => { return Math.abs(x - y) }
再次執行結果以下:
yarn run v1.21.1 $ mocha index.spec.js to test getAbs() √ should return 1 when the value is 1,2 √ should return 1 when the value is 2,1 √ should return 0 when the value is 1,1 √ should return 0 when the value is not present 4 passing (7ms) Done in 0.47s.
因此說,實際上 unit testing 視狀況來看,須要編寫不少的斷言,上面的測試雖然是經過了,但實際上還有有其餘的問題存在的,極端點來說好比傳遞的參數並非一個數字:
it('should return 0 when the value is not a number', () => { assert.equal(getAbs([1, 2, 3], 3), 0, 'getAbs() equal 0') })
JavaScript 並不像強類型語言那樣強硬,因此不少時候即使是錯誤的使用一個函數也只有在執行起來以後才能浮現錯誤。
嗯...因此說,單元測試中的斷言所能覆蓋的狀況要相對比較普遍才能夠,不然也只是片面的結論而已。
總感受一不當心就會走火入魔...
unit testing 目的是爲了使程序更加的健壯,穩定。可是相應的是須要編寫更多的代碼才能達到這個目的,因此如何正確的把握這個度,應該是一個值得思考的問題。
因此也只有更多的實踐才能夠找出一個比較滿意的答案吧。