AngularJS實際專案應用——單元測試框架設計
轉自:http://www.cnblogs.com/vipyoumay/p/5331787.html
關於本文:介紹通過karma與jsmine框架對angular開發的應用程式進行單元與E2E測試。
先決條件
- nodejs
- webstorm
建立專案
webstorm中建立空白web專案
建立html、js資料夾
在專案中建立2個資料夾分別用於存放專案中用到的html、js檔案。
安裝框架
安裝前端框架
專案中的前端框架主要為angularjs相關的框架,為了安裝框架方便可安裝bower包管理器。
1) 安裝bower包管理器
在webstorm的terminal中執行指令碼
npm install bower -save
2) 初始化bower.json檔案
執行指令碼生成bower.json檔案,用於管理bower的依賴和配置。
bower init
3) 安裝angular等框架
除了專案要用到的angular框架外還需要安裝angular-mocks框架
bower install bootstrap -save
bower install angular -save
bower install angular-mocks -save
安裝伺服器端框架
伺服器依賴於nodejs,需要安裝nodejs的包,首先在根目錄下建立package.json檔案。
1)安裝http-server模組
npm install http-server -save
2)安裝其他模組
- jasmine-core:javascript單元測試框架;
- karma:模擬javascript指令碼在各種瀏覽器執行的工具;
- karma-chrome-launcher: 在chrome瀏覽器執行的工具;
- karma-jasmine: jasmine-core在karma中的介面卡;
- karma-junit-reporter: 生成junit報告;
- protractor:E2E測試框架
啟動伺服器
要啟動node伺服器需要在package.json中配置script節點,dependencies中定義依賴包,在script配置start節點用於啟動伺服器,test節點的內容會在後面講解。
"name": "angularjs-test",
"version": "0.0.1",
"dependencies": {
"bower": "^1.7.7",
"http-server": "^0.9.0",
"jasmine-core": "^2.4.1",
"karma": "^0.13.22",
"karma-chrome-launcher": "^0.2.3",
"karma-jasmine": "^0.3.8",
"karma-junit-reporter": "^0.4.1",
"protractor": "^3.2.1"
},
"scripts": {
"postinstall": "bower install",
"prestart": "npm install",
"start": "http-server -a localhost -p 8000 -c-1",
"pretest": "npm install",
"test": "karma start karma.conf.js",
"test-single-run": "karma start karma.conf.js --single-run"
}
配置後執行命令,啟動伺服器,瀏覽器上輸入http://localhost:8000
npm start
開始單元測試
編寫功能程式碼
在檔案js中新建js檔案index.js。在index.js中定義congroller,實現簡單累加方法add,程式碼如下:
/** * Created by stephen on 2016/3/24. */
(function (angular) {
angular.module('app', []).
controller('indexCtrl', function ($scope) {
$scope.add = function (a, b) {
if(a&&b)
return Number(a) + Number(b)
return 0;
}
});
})(window.angular);
在檔案html中新建html檔案index.html,加入兩個輸入框使用者獲取輸入,當輸入後繫結controller中的add方法實現計算器功能,程式碼如下:
<!DOCTYPE html>
<html lang="en" ng-app="app"><head><meta charset="UTF-8"><title>index</title></head><body><div ng-controller="indexCtrl"><input type="text" ng-model="a" value="0">+<input type="text" ng-model="b" value="0">=<span id='result'>{{add(a,b)}}</span></div></body></html><script src="/bower_components/angular/angular.min.js"></script><script src="/bower_components/angular-mocks/angular-mocks.js"></script><script src="/js/index.js"></script>
啟動伺服器看到下圖效果
編寫測試程式碼
在test資料夾中新建檔案index-test.js用於編寫index.js的單元測試。
'use strict';
describe('app', function () {
beforeEach(module('app'));
describe('indexCtrl', function () {
it('add 測試', inject(function ($controller) {
var $scope = {};
//spec body
var indexCtrl = $controller('indexCtrl', {$scope: $scope});
expect(indexCtrl).toBeDefined();
expect($scope.add(2, 3)).toEqual(5);
}));
});
});
單元測試配置
初始化karma配置檔案,用於配置karma,執行命令
karma init
在karma配置檔案程式碼中每個節點都有預設註釋請參看
module.exports = function (config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: './',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
'bower_components/angular/angular.min.js',
'bower_components/angular-mocks/angular-mocks.js',
'js/index.js',
'test/index-test.js'
],
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['Chrome'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false,
plugins: [
'karma-chrome-launcher',
'karma-jasmine',
'karma-junit-reporter'
],
junitReporter: {
outputFile: '/test_out/unit.xml',
suite: 'unit'
}
})
}
在package.json scripts 配置測試資訊,指定karma檔案地址
"test": "karmastartkarma.conf.js",
執行單元測試
執行命令,執行測試
npm test
執行結果如下,可以看到通過測試:
除錯單元測試
除了執行測試外,很多時候需要除錯測試,在karma彈出網頁中點選debug,進入http://localhost:9876/debug.html頁面,就可以用chrome自帶的除錯工具除錯程式碼了:
單元測試覆蓋率
如果需要對單元測試覆蓋率進行統計,可以安裝karma-coverage並配置karma檔案。這樣在單元測試完成後,會生成測試覆蓋率報告文件。
npm install karma-coverage -save
在karma.conf.js檔案中加入節點
// 新增節點用於配置輸出資料夾
coverageReporter: {
type: 'html',
dir: 'coverage'
},
// 新增節點用於配置需要測試的檔案地址(這裡是controller地址)
preprocessors: {'js/*.js': ['coverage']}
// 新增元素'karma-coverage'
plugins: [
'karma-chrome-launcher',
'karma-jasmine',
'karma-junit-reporter',
'karma-coverage',
],
// 新增元素 coverage
reporters: ['progress', 'coverage'],
執行單元測試後在目錄中生成coverage資料夾,點選index.html可以檢視測試覆蓋率。
E2E測試
e2e或者端到端(end-to-end)或者UI測試是一種測試方法,它用來測試一個應用從頭到尾的流程是否和設計時候所想的一樣。簡而言之,它從一個使用者的角度出發,認為整個系統都是一個黑箱,只有UI會暴露給使用者。
配置E2E測試
新建資料夾e2e-test新建protractor.conf.js檔案,用於配置protractor框架,程式碼如下。
exports.config = {
allScriptsTimeout: 11000,
baseUrl: 'http://localhost:8000/app/',
// Capabilities to be passed to the webdriver instance.
capabilities: {
'browserName': 'chrome'
},
framework: 'jasmine',
// Spec patterns are relative to the configuration file location passed
// to protractor (in this example conf.js).
// They may include glob patterns.
specs: ['*.js'],
// Options to be passed to Jasmine-node.
jasmineNodeOpts: {
showColors: true, // Use colors in the command line report.
},
defaultTimeoutInterval: 30000
};
配置package.json scripts指令碼節點
"preupdate-webdriver": "npminstall",
"update-webdriver": "webdriver-managerupdate",
"preprotractor": "npmrunupdate-webdriver",
"protractor": "protractore2e-test/protractor.conf.js"
編寫e2e測試指令碼
設計測試用例:文字框a的值錄入1,文字框b錄入2,期望結果3
describe('index.html', function() {
beforeEach(function() {
browser.get('http://localhost:8000/html');
});
it('get index html', function() {
var a = element(by.model('a'));
var b = element(by.model('b'));
a.sendKeys(1);
b.sendKeys(2);
var result = element(by.id('result'));
expect(result.getText()).toEqual('3');
});
});
執行測試檢視測試結果
需要執行命名,檢視是否更新webdriver(什麼是webdriver http://sentsin.com/web/658.html),
手動安裝protractor至全域性npm
i -g protractor
注:安裝或更新webdriver需要FQ,請在webstrom中設定代理地址。
在webstrom
中切換至Terminal
視窗,在Terminal
視窗通過以下方式設定代理:
set PROXY=http://localhost:1080
set HTTP_PROXY=%PROXY%
set HTTPS_PROXY=%PROXY%
代理設定成功後,執行以下命令
npm run update-webdriver
執行e2e測試,這是會彈出瀏覽器,自動點選瀏覽器,錄入指令碼輸入完成自動化e2e測試,其本質還是呼叫selenium測試。
npm run protractor
參考資料
================================================================= 這裡我要說幾點: 1)controller中用了ngload類似的非同步載入機制,去載入檔案,在用karma跑的時候有時候會出錯,因為不能保證ngload已經把檔案載入進來了。我們看上面的測試case都是用$controller方法去例項化controller的,這樣就會出我說的問題。所以需要改用$injector.instantiate這個方法去例項化,用instantiate這個方法,對controller的寫法有要求,可以參考我介紹controller的文章,怎麼寫controller,下面看一個例子:var ldapCtrlInst = $injector.instantiate(LDAPCtrlDef,{
$scope:scope,
ldapSrv:ldapSrv,
uiGridUtils:{
createGridOptions:function(){return {};},
resetGridSelection:jasmine.createSpy('resetGridSelection')
},
modalUtils:{
showDlg:function(){
var deferred = $q.defer();
deferred.resolve("");
return deferred.promise;
}
}
});
上面程式碼中的LDAPCtrlDef是通過define把ldap.controller.js引入進來時的變數,然後$scope,ldapSrv,uiGridUtils等都是需要注入controller的引數。
2)由於是單元測試,不需要真正呼叫後臺的service,可以用下面的方式進行模擬
var deferred = $q.defer();
deferred.resolve({resultCode:"200",resultObject:[]});
spyOn(ldapSrv,'listLDAP').and.returnValue(deferred.promise);
3)在it方法裡記得呼叫scope.$digest();觸發angular的變數改變繫結機制