[JavaScript] 使用 QUnit 來做 JavaScript 的 Unit-testing
最近想來對自己寫的圖書館多重帳戶登入作一下架構的調整,
不過因為這個專案完全沒有 unit-testing 的程式,
因此遲遲沒有動手 (很怕大改時改爛了什麼東西…)
今天稍微查了一下 JavaScript 的 unit-testing framework,
老實說選項太多,有點難以抉擇…
最後決定來試用一下 jQuery 自己推出的 QUnit 囉~
1. 撰寫一個 unittest.html
下面的這個 unittest.html 是從 QUnit 官網的 Getting Started 範例拿來改的,
在裡面我先把專案裡要測試的 js 檔案 (及其相依的 js 檔案) 都先加進來,
接著直接引用了 CDN 上的 https://code.jquery.com/qunit/qunit-1.23.1.js,
後面再放我們寫的測試程式 (目前是只有一個 test_common.js):
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>QUnit for MultiLibraryLogin</title> <link rel="stylesheet" href="https://code.jquery.com/qunit/qunit-1.23.1.css"> </head> <body> <div id="qunit"></div> <div id="qunit-fixture"></div> <script src="../MultiLibraryLogin/jquery-2.1.3.min.js"></script> <script src="../MultiLibraryLogin/jquery-ui/jquery-ui.min.js"></script> <script src="../MultiLibraryLogin/jquery.scrollTo.min.js"></script> <script src="../MultiLibraryLogin/bootstrap/js/bootstrap.min.js"></script> <script src="../MultiLibraryLogin/cordova.js"></script> <script src="../MultiLibraryLogin/library_new_taipei_city.js"></script> <script src="../MultiLibraryLogin/library_taipei_city.js"></script> <script src="../MultiLibraryLogin/library_national_taiwan.js"></script> <script src="../MultiLibraryLogin/library_kaohsiung_city.js"></script> <script src="../MultiLibraryLogin/common.js"></script> <script src="../MultiLibraryLogin/version_changes.js"></script> <script src="../MultiLibraryLogin/popup.js"></script> <script src="https://code.jquery.com/qunit/qunit-1.23.1.js"></script> <script src="test_common.js"></script> </body> </html>
依照我個人的習慣,我會用一個測試檔案去對應一個原始碼檔案,
像我有個 common.js,那就會有一個測試用的 test_common.js,
只要把所有的 test_*.js 都列在 unittest.html 裡面就行了~
2. 撰寫 test_common.js
在測試程式裡面,就是用 QUnit.test() 來包裝一個 test case,
像下面我們定義了一個名叫 jsAppendToLen 的 test case,裡面有兩個 assertion,
這邊我比較喜歡用 assert.deepEqual 而不是 assert.equal,
因為前者對應的是 JavaScript 的 === 而後者是 ==,後者較容易有一些自動轉型造成的意外~
QUnit.test("jsAppendToLen", function(assert) { assert.deepEqual(jsAppendToLen("1", 3, "0"), "001"); assert.deepEqual(jsAppendToLen("9", 4, "0", false), "9000"); });
QUnit 的 assert 函式跟一般 xUnit 比較不同的是參數的順序,
像我用過的 shUnit2 和 GoogleTest 都是先放預期 (expected)的結果,
再放函式實際執行 (actual) 的結果,但 QUnit 正好相反,要記得這件事情,
不然列出錯誤訊息時可能會被誤導了~
assert 函式有許多種不同的確認方式,另外一種我目前有使用到的,
就是 assert.throws,用來確認這個函式會丟出一個 exception~
像是下面的 jsGetIndexFromId(“none”) 應該會遇到一個錯誤,這時就可以用 assert.throws 來捕捉:
QUnit.test("jsGetIndexFromId", function(assert) { assert.deepEqual(jsGetIndexFromId("12"), 12); assert.deepEqual(jsGetIndexFromId("data34"), 34); assert.deepEqual(jsGetIndexFromId("one56_two78"), 56); assert.throws(function() { jsGetIndexFromId("none"); }); });
3. 執行 unittest.html
在瀏覽器中打開 unittest.html,就會立刻執行 unit-testing 程式~
下面是執行的樣子:
如果待測程式或 unit-testing 程式裡有問題,導致結果不如預期,
QUnit 也會將錯誤的 test case 標示出來,同時把預期與實際的結果顯示出來:
目前 QUnit 用來起還算簡單易懂,希望可以好好用它寫一些測試程式,
這樣之後改程式就比較不會怕怕的了~
(不過其實對 AngularJS 提供的 Karma 這套 unit-testing framework 也挺有興趣的…
但在還不熟的狀況下,實在很難決定哪一種比較好,真是兩難呀~)