歡迎光臨
每天分享高質量文章

程式碼改寫率工具 Istanbul 入門教程

作者:阮一峰

網址:http://www.ruanyifeng.com/blog/2015/06/istanbul.html

測試的時候,我們常常關心,是否所有程式碼都測試到了。

這個指標就叫做“程式碼改寫率”(code coverage)。它有四個測量維度。

  • 行改寫率(line coverage):是否每一行都執行了?
  • 函式改寫率(function coverage):是否每個函式都呼叫了?
  • 分支改寫率(branch coverage):是否每個if程式碼塊都執行了?
  • 陳述句改寫率(statement coverage):是否每個陳述句都執行了?

Istanbul 是 JavaScript 程式的程式碼改寫率工具,本文介紹它的用法。

這個軟體以土耳其最大城市伊斯坦布林命名,因為土耳其地毯世界聞名,而地毯是用來改寫的。

一、安裝

Istanbul 是一個 npm 模組,安裝非常簡單,就一行命令。

$ npm install -g istanbul

二、改寫率測試

來看一個例子,怎麼使用 Istanbul 。下麵是指令碼檔案 simple.js 。

var a = 1;

var b = 1;

if ((a + b) > 2) {

console.log(‘more than two’);

}

使用 istanbul cover 命令,就能得到改寫率。

$ istanbul cover simple.js

===== Coverage summary =====

Statements : 75% ( 3/4 )

Branches : 50% ( 1/2 )

Functions : 100% ( 0/0 )

Lines : 75% ( 3/4 )

=============================

傳回結果顯示,simple.js 有4個陳述句(statement),執行了3個;有2個分支(branch),執行了1個;有0個函式,呼叫了0個;有4行程式碼,執行了3行。

這條命令同時還生成了一個 coverage 子目錄,其中的 coverage.json 檔案包含改寫率的原始資料,coverage/lcov-report 是可以在瀏覽器開啟的改寫率報告,其中有詳細資訊,到底哪些程式碼沒有改寫到。

三、改寫率門檻

完美的改寫率當然是 100%,但是現實中很難達到。需要有一個門檻,衡量改寫率是否達標。

istanbul check-coverage 命令用來設定門檻,同時檢查當前程式碼是否達標。

$ istanbul check-coverage –statement 90

ERROR: Coverage for statements (75%) does not meet global threshold (90%)

上面命令設定陳述句改寫率的門檻是 90% ,結果就報錯了,因為實際改寫率只有75%。

除了百分比門檻,我們還可以設定絕對值門檻,比如只允許有一個陳述句沒有被改寫到。

$ istanbul check-coverage –statement -1

上面命令使用負數,表示絕對值門檻。這樣一來,上面的例子就透過了改寫率測試,不會再報錯了。

百分比門檻和絕對值門檻,可以結合使用。

$ istanbul check-coverage –statement -5 –branch -3 –function 100

上面命令設定了3個改寫率門檻:5個陳述句、3個 if 程式碼塊、100%的函式。註意,這三個門檻是”與”(and)的關係,只要有一個沒有達標,就會報錯。

四、與測試框架的結合

實際開發時,istanbul 總是與測試框架結合使用,下麵以常用的 Mocha 框架為例。

sqrt.js 是一個計算平方根的指令碼。

var My = {

sqrt: function(x) {

if (x < 0) throw new Error(“負值沒有平方根”);

return Math.exp(Math.log(x)/2);

}

};

module.exports = My;

它的測試指令碼 test.sqrt.js 放在 test 子目錄。

var chai = require(‘chai’);

var expect = chai.expect;

var My = require(‘../sqrt.js’);

describe(“sqrt”, function() {

it(“4的平方根應該等於2”, function() {

expect(My.sqrt(4)).to.equal(2);

});

it(“引數為負值時應該報錯”, function() {

expect(function(){ My.sqrt(-1); }).to.throw(“負值沒有平方根”);

});

});

然後,執行下麵的命令得到程式碼改寫率。

$ istanbul cover _mocha

// or

$ istanbul cover _mocha test/test.sqrt.js

sqrt

✓ 4的平方根應該等於2

✓ 引數為負值時應該報錯

2 passing (7ms)

===== Coverage summary =====

Statements : 100% ( 5/5 )

Branches : 100% ( 2/2 )

Functions : 100% ( 1/1 )

Lines : 100% ( 4/4 )

=============================

上面命令中,istanbul cover 命令後面跟的是 _mocha 命令,前面的下劃線是不能省略的。

因為,mocha 和 _mocha 是兩個不同的命令,前者會新建一個行程執行測試,而後者是在當前行程(即 istanbul 所在的行程)執行測試,只有這樣, istanbul 才會捕捉到改寫率資料。其他測試框架也是如此,必須在同一個行程執行測試。

如果要向 mocha 傳入引數,可以寫成下麵的樣子。

$ istanbul cover _mocha — tests/test.sqrt.js -R spec

上面命令中,兩根連詞線後面的部分,都會被當作引數傳入 Mocha 。如果不加那兩根連詞線,它們就會被當作 istanbul 的引數(參考連結1,2)。

如果想在瀏覽器執行 Istanbul ,可以參考這篇文章。

五、忽略某些程式碼

istanbul 提供註釋語法,允許某些程式碼不計入改寫率。

var object = parameter || /* istanbul ignore next */ {};

上面程式碼是為 object 指定預設值(一個空物件)。如果由於種種原因,沒有為 object 為空物件的情況寫測試,可以用註釋,不將這種情況計入改寫率。註意,註釋要寫在”或”運運算元的後面。

/* istanbul ignore if */

if (hardToReproduceError)) {

return callback(hardToReproduceError);

}

上面程式碼的 if 陳述句塊,在計算改寫率的時候會被忽略。

贊(0)

分享創造快樂