代碼覆蓋率工具 istanbul

  • 2019 年 12 月 5 日
  • 筆記

本文作者:IMWeb 黎清龍 原文出處:IMWeb社區 未經同意,禁止轉載

代碼覆蓋率工具 istanbul

1. 代碼覆蓋率

在測試時,我們的用例把所有代碼都覆蓋了嗎? 對於這個問題引出了代碼覆蓋率的測試指標,一共有以下4種:

  • 行覆蓋率(line coverage):是否每一行都執行了?
  • 函數覆蓋率(function coverage):是否每個函數都調用了?
  • 分支覆蓋率(branch coverage):是否每個if代碼塊都執行了?
  • 語句覆蓋率(statement coverage):是否每個語句都執行了?

istanbul 是一個代碼覆蓋工具

它可以幫助我們檢查代碼的覆蓋率

在一個項目中,可以通過 istanbul 設定某些覆蓋率閾值來保證測試用例的齊全完整程度,用來保證代碼質量

下面是對 istanbul 的使用&學習所得

2. 安裝

需要安裝 mocha,should,istanbul

$ npm install mocha  $ npm install should  $ npm install istanbul

mocha 是測試框架,should 是斷言庫

3. 初探代碼覆蓋

先來看看我們的測試文件:

// index.js  function add(a, b) {    a = a || 0;    b = b || 0;    return a + b;  }    add(1, 2);

很簡單的一個兩位數相加的函數,好,我們執行命令:

$ .node_modules.binistanbul cover index.js

得出下面的結果:

============ Coverage summary ============  Statements   : 100% ( 5/5 )  Branches     : 50% ( 2/4 )  Functions    : 100% ( 1/1 )  Lines        : 100% ( 5/5 )  ==========================================

可以看到,列出了4個覆蓋率指標的結果

結果表示,語句,代碼行還有函數都是100%執行了,但是並不是所有分支都執行過了

那麼具體哪些分支沒有被執行?

我們可以通過自己肉眼去查看,並且通過大腦去「執行」代碼,這是笨方法

istanbul 給我們提供了一個直觀的查看結果的方式:網頁版結果報告

在執行了命令之後,在當前目錄你會發現新生成了一個文件夾:coverage

這個文件夾下面包含了代碼覆蓋率結果文件以及代碼覆蓋率結果報告

直接打開coverage/lcov-report/index.html,會在瀏覽器看到以下頁面:

這個頁面通過一個很直觀的方式來展示每個文件夾下面的文件的代碼覆蓋率

點擊文件夾,可以看到每個具體的文件的代碼覆蓋率情況:

點擊文件名,我們就可以看到該文件的源代碼,以及一些代碼未有覆蓋的情況:

可以看到上面有兩個地方標了黃色,也就是說代碼沒有執行到那些地方

3.1 初探小結

  • 代碼覆蓋率不一定是要在測試當中,只是通常代碼覆蓋率用於測試
    • 對於一些自啟動的模塊,是可以通過代碼覆蓋率工具去檢查代碼的執行情況,通過這個方式去查找一些冗餘的代碼,比如一些永遠都不會被執行到的代碼
    • 對於非自啟動的模塊,比如一些庫,他們都是被其他代碼調用的,這個時候就需要用到單元測試了;單元測試的本質就是測試驗證某個模塊是否正確可用,它通過創建一些模塊依賴的stub,並且編寫啟動代碼去調用模塊的接口來完成這個目標;通過代碼覆蓋率工具,我們可以知道測試用例是否齊全,覆蓋到了「足夠多」的代碼
  • 4個指標當中,行覆蓋率和語句覆蓋率很相近;在代碼規範的情況下,它們應該是一樣的,因為我們規範要求一行寫一個語句
  • 4個指標當中,分支覆蓋率是最重要的,它包括:
    • !, &&, ||, ?:
    • ifelse
    • switch - case
    • 等等各種包含分支的情況

4. 配合測試

還是剛剛的例子,這次我們改一下:

// index.js  function add(a, b) {    a = a || 0;    b = b || 0;    return a + b;  }    module.exports = add;

這樣,我們就得到了一個非自啟動的模塊

那麼,我們需要編寫單元測試:

var should = require('should');  var add = require('./index');    describe('add', () => {    it('1 + 2', () => {      add(1, 2).should.be.equal(3);    });  });

然後我們執行命令:

$ .node_modules.binistanbul cover .node_modulesmochabin_mocha -- test.js

結果如下:

============ Coverage summary ============  Statements   : 100% ( 10/10 )  Branches     : 50% ( 2/4 )  Functions    : 100% ( 1/1 )  Lines        : 100% ( 10/10 )  ==========================================

注意:這裡結果和之前不一樣是因為這裡還統計了測試用例自身的代碼覆蓋率情況 這是在 windows 系統,所以需要用 .node_modulesmochabin下面的 mocha mocha 前面加的下劃線是不能省略的 因為,mocha_mocha 是兩個不同的命令,前者會新建一個進程執行測試,而後者是在當前進程(即 istanbul 所在的進程)執行測試,只有這樣, istanbul 才會捕捉到覆蓋率數據。其他測試框架也是如此,必須在同一個進程執行測試 -- 後面的部分,都會被當作參數傳入 mocha 。如果不加,它們就會被當作 istanbul 的參數

4.1 檢測代碼覆蓋率閾值

執行下面命令:

$ .node_modules.binistanbul check-coverage --statement 90 --branch 90 --function 90

這行命令的意思是檢查代碼覆蓋率結果是否超過閾值指標,這裡設置了指標是:語句覆蓋率要超過 90%,分支覆蓋率要超過 90%,函數覆蓋率要超過 90%

結果如下:

ERROR: Coverage for branches (50%) does not meet global threshold (90%)

結果提示說分支覆蓋率沒有打到指標。。。

4.2 新增測試用例

通過查看代碼覆蓋率結果報告,知道我們忽略了哪些分支情況後,我們就要需要添加新的測試用例去覆蓋這些情況:

var should = require('should');  var add = require('./index');    describe('add', () => {    it('1 + 2', () => {      add(1, 2).should.be.equal(3);    });      it('1 + undefined', () => {      add(1).should.be.equal(1);    });      it('undefined + 2', () => {      add(undefined, 2).should.be.equal(2);    });  });

這次我們再執行代碼覆蓋率檢查命令:

$ .node_modules.binistanbul cover .node_modulesmochabin_mocha -- test.js

會得到這樣的結果:

============ Coverage summary ============  Statements   : 100% ( 14/14 )  Branches     : 100% ( 4/4 )  Functions    : 100% ( 1/1 )  Lines        : 100% ( 14/14 )  ==========================================

這一次,我們再執行代碼覆蓋率閾值檢測命令:

$ .node_modules.binistanbul check-coverage --statement 90 --branch 90 --function 90

就不會有報錯信息了

5 小結

在真實項目中,代碼覆蓋率工具可以幫助我們完善測試用例,保證代碼及項目的質量

通常在測試自動化的基礎上,我們再加上代碼覆蓋率的自動化閾值檢測,用來保證測試用例的完整性