來,加入前端自動化單元測試

最近閒來無事,開始摸索前端單元測試。一是不備之需,二是確實在實際項目中可以用到單元測試。這樣能夠提升開發效率,提高代碼質量,徹底能夠單獨對 JS 進行測試,無需頁面,不依賴其餘第三方。javascript

爲何須要單元測試

在這裏首先須要知道單元測試的目的及結果:html

  1. 使代碼健壯,質量高,兼容各類臨界點;前端

  2. 減小 QA 測試報告的反饋,提升自我影響力;java

  3. 保證代碼的整潔清晰。node

若是須要刨根問底追究爲何須要進行單元測試,那咱們能夠開始講講實際項目開發中遇到的一些問題:git

  1. QA 不斷反饋代碼有 BUG (此時你正在投入的開發,而後被打擾...);github

  2. 代碼出現 BUG,疊加代碼修復 BUG(代碼愈來愈難維護...);web

  3. 已經開發完成一個模塊,可是沒有頁面提供調試測試;chrome

  4. 你開發完成的功能,每次都有許多細小的 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 我就不介紹,網上一搜一大把介紹:

  1. 安裝 node 環境

    • 依賴於 node 做爲基礎環境,安裝完成在控制檯運行下面命令查看是否安裝成功。

    node -v
  2. 新建目錄並經過如下命令初始化項目配置 package.json

    npm init

    在 package.json scripts: {} 添加如下內容:

    "test": "karma start karma.conf.js"
  3. 依次安裝測試框架

    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
  4. 運行如下命令新建 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'
            ]
        })
    }
  5. 新建源代碼及測試代碼目錄,目錄結構以下:

    project
        - node_modules
            - *(node 模塊)
        - src
            - FQA
                - index.js
        - test
            - unit
                - specs
                    - *.spec.js
        - karma.conf.js
        - package.json
  6. 測試代碼

    • 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);
        });
    });
  7. 運行 sudo npm run test 執行測試代碼

    "scripts": {
        "test": "karma start karma.conf.js"
    }
  8. 結果:
    運行結果

解答

  1. npm run test 運行的其實是 package.json 中配置的命令:

    "test": "karma start karma.conf.js"
  2. describe 定義測試模塊,it 測試一個單元,describe 內部能夠同時定義多個 it,所以能夠作一系列的單元測試,測試方法詳見官方文檔

  3. karma.conf.js 配置 files 設置測試時須要被加載的文件

    files: [
        './src/**/*.js',
        './test/unit/specs/*.spec.js'
    ]

總結

但願看完這篇文章,你也可以動起手來,開始編寫一些單元測試代碼,提升代碼的質量,提高本身的周圍影響力。本篇文章內容表述了實際項目開發中會遇到的問題,咱們能夠經過單元測試來減小這類問題的發生,以提升代碼的安全性,代碼的質量,從而保證產品的穩定性。點擊此處查看更多文章

相關文章
相關標籤/搜索