最近閒來無事,開始摸索前端單元測試。一是不備之需,二是確實在實際項目中可以用到單元測試。這樣能夠提升開發效率,提高代碼質量,徹底能夠單獨對 JS 進行測試,無需頁面,不依賴其餘第三方。javascript
在這裏首先須要知道單元測試的目的及結果:html
使代碼健壯,質量高,兼容各類臨界點;前端
減小 QA 測試報告的反饋,提升自我影響力;java
保證代碼的整潔清晰。node
若是須要刨根問底追究爲何須要進行單元測試,那咱們能夠開始講講實際項目開發中遇到的一些問題:git
QA 不斷反饋代碼有 BUG (此時你正在投入的開發,而後被打擾...);github
代碼出現 BUG,疊加代碼修復 BUG(代碼愈來愈難維護...);web
已經開發完成一個模塊,可是沒有頁面提供調試測試;chrome
你開發完成的功能,每次都有許多細小的 BUG(我的影響力降低...)。npm
好了,列舉了這麼多緣由,相信你也開始心虛了,回去繼續搬磚檢查檢查代碼有沒有問題,若是你面色從容,大神,請手下個人膝蓋。
總結:單元測試的目的只有一個,用來肯定是否適合使用
若是明白了爲何要進行單元測試,相信你已經能夠開始着手爲本身的代碼寫一些單元測試代碼。測試從字面理解就是檢驗,看對象是否達標,達標就是 pass,不達標就是 fail。產品有這樣一個需求,若是結果是 3 達到目標且返回的爲有效的數字類型才能夠進行比較,下面看個栗子:
/** * 獲取 a 除以 b 的結果 * @param {[Number]} a [數字] * @param {[Number]} b [數字] * @return {[Number]} [結果數字] */ function division(a, b) { return a / b; } // 測試代碼 function test() { var result = division(6, 2); if (result === 3) { console.log('pass'); } else { console.log('fail'); } }
咋一看上面的代碼沒什麼問題,能夠知足產品的需求,可是問題來了,若是 b 爲 0,這個模塊就出現了 BUG,同時若是下次須要達到其餘的值就算經過,那就得去修改測試代碼,這樣的測試代碼自己也太不健全。因而乎有了下面的方式:
/** * 獲取 a 除以 b 的結果 * @param {[Number]} a [數字] * @param {[Number]} b [數字] * @return {[Number]} [結果數字] */ function division(a, b) { if (b === 0) { return 0; } else { return a / b; } } function test(name, result, expect) { if (result === expect) { console.log(name + '-> pass'); } else { console.log(name + '-> fail'); } } test('normal number', division(6, 2), 3); test('zero', division(6, 0), 0);
若是須要指望值爲 10 就經過,那能夠這樣:
test('normal number is 10', division(20, 2), 10);
可是隨着前端迅速的發展,也出現了不少測試框架,下面我演示我在實際項目中使用的測試框架環境配置 karma + jasmine,對於 karma、jasmine 我就不介紹,網上一搜一大把介紹:
安裝 node 環境
依賴於 node 做爲基礎環境,安裝完成在控制檯運行下面命令查看是否安裝成功。
node -v
新建目錄並經過如下命令初始化項目配置 package.json
npm init
在 package.json scripts: {} 添加如下內容:
"test": "karma start karma.conf.js"
依次安裝測試框架
npm install karma -g npm install jasmine --save-dev npm install karma-jasmine --save-dev npm install karma-chrome-launcher --save-dev npm install jasmine-core --save-dev
或者一次性安裝
npm install karma -g npm install jasmine karma-jasmine karma-chrome-launcher jasmine-core --save-dev
運行如下命令新建 karma.conf.js(根目錄下不是必須)
karma init
文件內容及說明:
/** * karma 自動化測試參數配置 */ module.exports = function(config) { config.set({ // 基礎路徑,用在files,exclude屬性上 basePath: '', // 可用的測試框架: https://npmjs.org/browse/keyword/karma-adapter frameworks: ['jasmine'], // 須要加載到瀏覽器的文件列表 files: [ './src/**/*.js', './test/unit/specs/*.spec.js' ], // 排除的文件列表 exclude: [ 'karma.conf.js' ], // 在瀏覽器使用以前處理匹配的文件 // 可用的預處理: https://npmjs.org/browse/keyword/karma-preprocessor preprocessors: {}, // 使用測試結果報告者 // 可能的值: "dots", "progress" // 可用的報告者: https://npmjs.org/browse/keyword/karma-reporter reporters: ['progress'], // web server port port: 9876, // 啓用或禁用輸出報告或者日誌中的顏色 colors: true, /** * 日誌等級 * 可能的值: * config.LOG_DISABLE //不輸出信息 * config.LOG_ERROR //只輸出錯誤信息 * config.LOG_WARN //只輸出警告信息 * config.LOG_INFO //輸出所有信息 * config.LOG_DEBUG //輸出調試信息 */ // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG logLevel: config.LOG_INFO, // 啓用或禁用自動檢測文件變化進行測試 autoWatch: true, // 測試啓動的瀏覽器 // 可用的瀏覽器: https://npmjs.org/browse/keyword/karma-launcher browsers: ['Chrome'], // 開啓或禁用持續集成模式 // 設置爲true, Karma將打開瀏覽器,執行測試並最後退出 singleRun: false, // 併發級別(啓動的瀏覽器數) concurrency: Infinity, // 依賴插件 plugins: [ 'karma-chrome-launcher', 'karma-jasmine' ] }) }
新建源代碼及測試代碼目錄,目錄結構以下:
project - node_modules - *(node 模塊) - src - FQA - index.js - test - unit - specs - *.spec.js - karma.conf.js - package.json
測試代碼
index.js 源碼
/** - test map method callback and parseInt param use - @return {[Array]} [Array] */ function checkMap() { var nums = ['1', '2', '3']; return nums.map(parseInt); } /** - test null is Object,and common object is same - @return {[Array]} [Array] */ function typeofAndInstanceOf() { var result = []; result.push(typeof null); result.push(null instanceof Object); return result; } /** - 檢測操做符優先級 - @return {[string]} [返回字符串] */ function checkOperators() { var result = 'autoTest'; result = 'Value is ' + (result === 'autoTest') ? 'Something' : 'Nothing'; return result; }
fqa.spec.js 測試代碼
/** - test index.js checkMap method - detail: - parseInt(val, base), base is 2 ~ 36, otherwise value equal NaN. */ describe('test map and callback parseInt', function() { it('a array call map', function() { var nums = checkMap(); console.log(nums); expect([1, NaN, NaN]).toEqual(nums); }); }); /** - test index.js typeofAndInstanceOf method - detail: - typeof null qeual 'object', but null instanceof Object equal false, because null Constructor not Object. */ describe('test null is object', function() { it('null object', function() { var result = typeofAndInstanceOf(); console.log(result); expect(['object', false]).toEqual(result); }); }); /** - test index.js checkOperators method - detail: - compare operator precedence, + gt ?. */ describe('test null is object', function() { it('test operator preceence', function() { var result = checkOperators(); console.log(result); expect('Something').toEqual(result); }); });
運行 sudo npm run test 執行測試代碼
"scripts": { "test": "karma start karma.conf.js" }
結果:
npm run test 運行的其實是 package.json 中配置的命令:
"test": "karma start karma.conf.js"
describe 定義測試模塊,it 測試一個單元,describe 內部能夠同時定義多個 it,所以能夠作一系列的單元測試,測試方法詳見官方文檔。
karma.conf.js 配置 files 設置測試時須要被加載的文件
files: [ './src/**/*.js', './test/unit/specs/*.spec.js' ]
但願看完這篇文章,你也可以動起手來,開始編寫一些單元測試代碼,提升代碼的質量,提高本身的周圍影響力。本篇文章內容表述了實際項目開發中會遇到的問題,咱們能夠經過單元測試來減小這類問題的發生,以提升代碼的安全性,代碼的質量,從而保證產品的穩定性。點擊此處查看更多文章。