來源:http://www.cnblogs.com/haogj/p/5204126.htmljavascript
關於 Karma 會是一個系列,討論在各類環境下,使用 Karma 進行單元測試。html
本文討論 karma 集成 Jasmine 進行單元測試。java
實現初始化 NPM 包管理,建立 package.json 項目管理文件。node
使用參數 -y 直接按照默認值建立 packgae.json 項目管理文件。chrome
PS C:\study\mykarma> npm init -y
Wrote to C:\study\mykarma\package.json:
{
"name": "mykarma", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC" }
如今,能夠在項目文件夾中看到 package.json 文件已經建立了。npm
如今,能夠直接使用 NPM 來安裝 karma。json
i 是 install 命令的縮寫,-D 是 --save-dev 的縮寫。瀏覽器
PS C:\study\mykarma> npm i -D karma npm WARN package.json mykarma@1.0.0 No description npm WARN package.json mykarma@1.0.0 No repository field. npm WARN package.json mykarma@1.0.0 No README data npm WARN optional dep failed, continuing fsevents@1.0.7 karma@0.13.21 node_modules\karma ├── batch@0.5.3 ├── di@0.0.1 ├── graceful-fs@4.1.3 ├── rimraf@2.5.2 ├── mime@1.3.4 ├── colors@1.1.2 ├── source-map@0.5.3 ├── isbinaryfile@3.0.0 ├── bluebird@2.10.2 ├── dom-serialize@2.2.1 (custom-event@1.0.0, void-elements@2.0.1, extend@3.0.0, ent@2.2.0) ├── http-proxy@1.13.2 (eventemitter3@1.1.1, requires-port@1.0.0) ├── optimist@0.6.1 (wordwrap@0.0.3, minimist@0.0.10) ├── glob@7.0.0 (path-is-absolute@1.0.0, inherits@2.0.1, once@1.3.3, inflight@1.0.4) ├── useragent@2.1.8 (lru-cache@2.2.4) ├── minimatch@3.0.0 (brace-expansion@1.1.3) ├── lodash@3.10.1 ├── expand-braces@0.1.2 (array-unique@0.2.1, array-slice@0.2.3, braces@0.1.5) ├── log4js@0.6.31 (semver@4.3.6, readable-stream@1.0.33) ├── connect@3.4.1 (utils-merge@1.0.0, parseurl@1.3.1, debug@2.2.0, finalhandler@0.4.1) ├── core-js@2.1.0 ├── body-parser@1.15.0 (content-type@1.0.1, bytes@2.2.0, depd@1.1.0, raw-body@2.1.5, debug@2.2.0, qs@6.1.0, iconv-lite@0.4.13, http-errors@1.4.0, on-finished@2.3.0, type-is@1.6.11) ├── socket.io@1.4.5 (debug@2.2.0, has-binary@0.1.7, socket.io-parser@2.2.6, socket.io-adapter@0.4.0, engine.io@1.6.8, socket.io-client@1.4.5) └── chokidar@1.4.2 (path-is-absolute@1.0.0, inherits@2.0.1, async-each@0.1.6, glob-parent@2.0.0, is-binary-path@1.0.1, is-glob@2.0.1, readdirp@2.0.0, anymatch@1.3.0)
PS C:\study\mykarma>
如今咱們可使用 node 來運行 karma 了。app
>node ./node_modules/karma/bin/karma
爲了能在命令行直接執行 karma 命令,咱們再按着一個 karma-cli.dom
-g 表示全局安裝,這樣能夠在系統的任何文件夾中直接執行 karma 命令。
PS C:\study\mykarma> npm i -g karma-cli
C:\Users\XXX\AppData\Roaming\npm\karma -> C:\Users\XXX\AppData\Roaming\npm\node_modules\karma-cli\bin\karma karma-cli@0.1.2 C:\Users\guanjun\AppData\Roaming\npm\node_modules\karma-cli └── resolve@1.1.7
安裝以後,能夠直接使用 karma 來啓動測試了,首先檢查一下當前的版本。
PS C:\study\mykarma> karma --version
Karma version: 0.13.21 PS C:\study\mykarma>
祝賀你, 基本的 Karma 已經安裝成功了。
咱們使用 Karma 來驅動單元測試,因此只有 Karma 是不行的,還須要安裝單元測試庫以便運行測試腳本,安裝測試庫與 Karma 的適配器,還有各類瀏覽器的適配器。
這裏咱們安裝 Jasmine 的測試支持和 chrome 瀏覽器的適配器。
對於 jasmine 來講,咱們須要 Jasmine 的適配器,還必須有 jasmine-core 庫。
karma-chrome-launcher 則提供了 karma 與 chrome 的適配器。
PS C:\study\mykarma> npm i -D jasmine-core karma-jasmine karma-chrome-launcher
npm WARN package.json mykarma@1.0.0 No description npm WARN package.json mykarma@1.0.0 No repository field. npm WARN package.json mykarma@1.0.0 No README data npm WARN peerDependencies The peer dependency jasmine-core@* included from karma-jasmine will no npm WARN peerDependencies longer be automatically installed to fulfill the peerDependency npm WARN peerDependencies in npm 3+. Your application will need to depend on it explicitly. jasmine-core@2.4.1 node_modules\jasmine-core karma-jasmine@0.3.7 node_modules\karma-jasmine karma-chrome-launcher@0.2.2 node_modules\karma-chrome-launcher ├── fs-access@1.0.0 (null-check@1.0.0) └── which@1.2.4 (isexe@1.1.2, is-absolute@0.1.7)
如今涉及單元測試的基本工具已經安裝就緒了。
karma 支持三個命令。
Karma 須要進行配置,配置文件比較複雜,可使用 karma 提供的 init 命令來直接建立基礎的配置文件。在處理過程當中,咱們可使用交互方式提供測試的信息,Karma 根據這些信息生成一個基本的配置文件。配置文件的默認名稱是 karma.conf.js。若是你提供了配置文件的名稱,karma 會將配置信息寫入到你提供的文件名中。
建立 Karma 配置文件
PS C:\study\mykarma> karma init
Which testing framework do you want to use ? Press tab to list possible options. Enter to move to the next question. > jasmine Do you want to use Require.js ? This will add Require.js plugin. Press tab to list possible options. Enter to move to the next question. > no Do you want to capture any browsers automatically ? Press tab to list possible options. Enter empty string to move to the next qu ion. > Chrome > What is the location of your source and test files ? You can use glob patterns, eg. "js/*.js" or "test/**/*Spec.js". Enter empty string to move to the next question. > src/**/*.js 20 02 2016 22:32:26.698:WARN [init]: There is no file matching this pattern. > test/**/*.spec.js 20 02 2016 22:33:26.513:WARN [init]: There is no file matching this pattern. > Should any of the files included by the previous patterns be excluded ? You can use glob patterns, eg. "**/*.swp". Enter empty string to move to the next question. > Do you want Karma to watch all the files and run the tests on change ? Press tab to list possible options. > yes Config file generated at "C:\study\mykarma\karma.conf.js". PS C:\study\mykarma>
因爲咱們沒有提供配置文件名稱,這裏生成的是默認的配置文件 karma.conf.js 。
因爲已經有了 karma 配置文件,如今可使用 karma start 啓動 karma 了,因爲尚未測試,因此看不到測試結果是正常的。
須要注意的是 karma 配置中的 singleRun 這個參數,設置爲 false 的話,karma 會自動監控測試環境,默認是 Chrome, 若是你關掉了,karma 會自動從新啓動一個。若是配置爲 true,執行一次測試以後,karma 會自動停掉。
在 singleRun 爲 false 的狀況下,執行的結果多是這樣的。
PS C:\study\mykarma> karma start
22 02 2016 10:54:11.796:INFO [karma]: Karma v0.13.21 server started at http://localhost:9876/ 22 02 2016 10:54:11.806:INFO [launcher]: Starting browser Chrome 22 02 2016 10:54:13.206:INFO [Chrome 47.0.2526 (Windows 7 0.0.0)]: Connected on socket /#rbiYFxG0uTVJxpVoAAAA with id 13601272
如今咱們可使用 Jasmine 開始寫測試了。
在項目文件夾中,建立一個名爲 test 的子文件夾來保存測試用例。而後在 test 文件夾中建立一個 unit 的文件夾來保存單元測試用例。
在這個文件夾中建立一個名爲 hello.spec.js 的測試文件。
通常來講,咱們會爲測試用例的文件名稱提供一個特定的模式,以便對測試用例進行統一處理,這裏咱們約定測試用例的文件名以 .spec.js 爲結尾。
hello.spec.js
describe('hello, unit test.', function(){ it('should also be able to test', function(){ expect(true).toBe(true); }); it('should be failed', function(){ expect(true).toBe(false); }) });
這個測試包含了兩個測試用例,一個必定成功,一個必定失敗。
確認在咱們 karma 的配置文件中,包含了咱們的測試用例。
// list of files / patterns to load in the browser files: [ 'test/**/*.spec.js' ],
如今,使用 karma start 啓動測試,在控制檯應該會看到以下的輸出。
PS C:\study\mykarma> karma start
22 02 2016 11:09:31.137:WARN [karma]: No captured browser, open http://localhost:9876/ 22 02 2016 11:09:31.157:INFO [karma]: Karma v0.13.21 server started at http://localhost:9876/ 22 02 2016 11:09:31.167:INFO [launcher]: Starting browser Chrome 22 02 2016 11:09:32.561:INFO [Chrome 47.0.2526 (Windows 7 0.0.0)]: Connected on socket /#ymfXfb-xI2a3fZ82AAAA with id 31292195 Chrome 47.0.2526 (Windows 7 0.0.0) hello, unit test. should be failed FAILED Expected true to be false. at Object.<anonymous> (C:/study/mykarma/test/unit/hello.spec.js:7:20) Chrome 47.0.2526 (Windows 7 0.0.0): Executed 2 of 2 (1 FAILED) (0.016 secs / 0.006 secs)
能夠看到執行了兩個測試,其中一個失敗了,失敗的測試爲 hello, unit test 中的 should be failed 測試用例。
在項目文件夾中,建立一個名爲 src 的子文件夾來保存咱們的應用代碼,在其中建立一個名爲 add.js 的腳本文件,咱們未來測試它的工做是否正確。
function add(a, b){ return a + b; }
這個腳本很是簡單,僅僅用來計算兩個數字以後,沒有任何的驗證。
而後,咱們針對它寫兩個測試用例,保存到 ./test/unit/add.spec.js 文件中。
describe('add function unit test.', function(){ it('2 + 3 = 5', function(){ var result = add( 2, 3 ); expect( result ).toBe( 5 ); }); it('2 + 3 = 6, this should faild.', function(){ var result = add( 2, 3 ); expect(result).toBe( 6 ); }) });
確認你的 karma 配置文件中,包含了被測試代碼和測試代碼。
// list of files / patterns to load in the browser files: [ 'src/**/*.js', 'test/**/*.spec.js' ],
如今的控制檯輸出應該是這樣的。
PS C:\study\mykarma> karma start
22 02 2016 11:22:18.800:WARN [karma]: No captured browser, open http://localhost:9876/ 22 02 2016 11:22:18.810:INFO [karma]: Karma v0.13.21 server started at http://localhost:9876/ 22 02 2016 11:22:18.820:INFO [launcher]: Starting browser Chrome 22 02 2016 11:22:20.232:INFO [Chrome 47.0.2526 (Windows 7 0.0.0)]: Connected on socket /#i6GaDaxNTy8HWL52AAAA with id 89457157 Chrome 47.0.2526 (Windows 7 0.0.0) add function unit test. 2 + 3 = 6, this should faild. FAILED Expected 5 to be 6. at Object.<anonymous> (C:/study/mykarma/test/unit/add.spec.js:9:24) Chrome 47.0.2526 (Windows 7 0.0.0) hello, unit test. should be failed FAILED Expected true to be false. at Object.<anonymous> (C:/study/mykarma/test/unit/hello.spec.js:7:20) Chrome 47.0.2526 (Windows 7 0.0.0): Executed 4 of 4 (2 FAILED) (0.021 secs / 0.007 secs)
祝賀你,如今你已經能夠測試你的代碼了!
若是你的應用是由一個一個獨立的函數定義出來的,如今就已經能夠進行測試了。
在 Karma 啓動的瀏覽器界面中,能夠看到當前的執行狀態。
點擊 DEBUG 按鈕,能夠進入實際的測試頁面。
這個頁面看起來是空白的,可是執行了實際的測試腳本,進入瀏覽器的開發者模式,能夠看到實際的內容。好比,咱們上面的實際執行內容。
查看頁面源碼,能夠看到這個 Karma 生成的頁面。
<!doctype html> <!-- This file is almost the same as context.html - loads all source files, but its purpose is to be loaded in the main frame (not within an iframe), just for immediate execution, without reporting to Karma server. --> <html> <head> <title>Karma DEBUG RUNNER</title> <link href="favicon.ico" rel="icon" type="image/x-icon" /> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" /> </head> <body> <!-- The scripts need to be at the end of body, so that some test running frameworks (Angular Scenario, for example) need the body to be loaded so that it can insert its magic into it. If it is before body, then it fails to find the body and crashes and burns in an epic manner. --> <script type="text/javascript"> window.__karma__ = { info: function(info) { if (info.dump && window.console) window.console.log(info.dump); }, complete: function() { if (window.console) window.console.log('Skipped ' + this.skipped + ' tests'); }, store: function() {}, skipped: 0, result: window.console ? function(result) { if (result.skipped) { this.skipped++; return; } var msg = result.success ? 'SUCCESS ' : 'FAILED '; window.console.log(msg + result.suite.join(' ') + ' ' + result.description); for (var i = 0; i < result.log.length; i++) { window.console.error(result.log[i]); } } : function() {}, loaded: function() { this.start(); } }; window.__karma__.config = {"args":[],"useIframe":true,"captureConsole":true,"clearContext":true}; // All served files with the latest timestamps window.__karma__.files = { '/base/node_modules/jasmine-core/lib/jasmine-core/jasmine.js': '391e45351df9ee35392d2e5cb623221a969fc009', '/base/node_modules/karma-jasmine/lib/boot.js': '4a7da64f416169520c9d5c43b5a7feac6bde9104', '/base/node_modules/karma-jasmine/lib/adapter.js': 'd76809fbd57147a108ceb7fe2c134b2d39806a9a', '/base/src/add.js': 'dd99cc5693226f200581da90d5f231a95e6bb720', '/base/test/unit/add.spec.js': 'f430471235f184ab5e13c14ccb87740b833487d6', '/base/test/unit/hello.spec.js': '5b7173f9c7e05f6aadc798a5065cd6dc572d005d' }; </script> <!-- Dynamically replaced with <script> tags --> <script type="text/javascript" src="/base/node_modules/jasmine-core/lib/jasmine-core/jasmine.js"></script> <script type="text/javascript" src="/base/node_modules/karma-jasmine/lib/boot.js"></script> <script type="text/javascript" src="/base/node_modules/karma-jasmine/lib/adapter.js"></script> <script type="text/javascript" src="/base/src/add.js"></script> <script type="text/javascript" src="/base/test/unit/add.spec.js"></script> <script type="text/javascript" src="/base/test/unit/hello.spec.js"></script> <script type="text/javascript"> window.__karma__.loaded(); </script> </body> </html>
關鍵的內容在頁面的後部。
<!-- Dynamically replaced with <script> tags --> <script type="text/javascript" src="/base/node_modules/jasmine-core/lib/jasmine-core/jasmine.js"></script> <script type="text/javascript" src="/base/node_modules/karma-jasmine/lib/boot.js"></script> <script type="text/javascript" src="/base/node_modules/karma-jasmine/lib/adapter.js"></script> <script type="text/javascript" src="/base/src/add.js"></script> <script type="text/javascript" src="/base/test/unit/add.spec.js"></script> <script type="text/javascript" src="/base/test/unit/hello.spec.js"></script> <script type="text/javascript"> window.__karma__.loaded(); </script>
在這個頁面,咱們能夠在源碼中設置斷點,檢查測試。
能夠看到,使用 Karma 集成 Jasmine 測試是很方便的組合。