前台自動化測試環境搭建
前言
在Java領域,Apache, Spring, JBoss 三大社區的開源庫,包羅萬象,但每個庫都在其領域中都鶴立雞群。而Nodejs中各種各樣的開源庫,卻讓人眼花繚亂,不知從何下手。
Nodejs領域: Jasmine做單元測試,Karma自動化完成單元測試,Grunt啟動Karma統一項目管理,Yeoman最后封裝成一個項目原型模板,npm做nodejs的包依賴管理,bower做javascript的包依賴管理。
Java領域:JUnit做單元測試, Maven自動化單元測試,統一項目管理,構建項目原型模板,包依賴管理。
Nodejs讓組合變得更豐富,卻又在加重我們的學習門檻。我還說不清楚,也看不透!
上面寫的有點遠了,回到文章的主題,Jasmine+Karma自動化單元測試。
1.Karma簡介
Karma是Testacular的新名字,在2012年google開源了Testacular,2013年Testacular改名為Karma。Karma是一個讓人感到非常神秘的名字,表示佛教中的緣分,因果報應,比Cassandra這種名字更讓人猜不透!
Karma是一個基於Node.js的JavaScript測試執行過程管理工具(Test Runner)。該工具可用於測試所有主流Web瀏覽器,也可集成到CI(Continuous integration)工具,也可和其他代碼編輯器一起使用。這個測試工具的一個強大特性就是,它可以監控(Watch)文件的變化,然后自行執行,通過console.log顯示測試結果。
Jasmine是單元測試框架,本單將介紹用Karma讓Jasmine測試自動化完成。
istanbul是一個單元測試代碼覆蓋率檢查工具,可以很直觀地告訴我們,單元測試對代碼的控制程度。
2.Jasmine簡介
Jasmine是一個用來編寫Javascript測試的框架,它不依賴於任何其它的javascript框架,也不需要DOM。它有擁有靈巧而明確的語法可以讓你輕松的編寫測試代碼。
jasmine的結構很簡單:
describe("A suite", function() {
var foo;
beforeEach(function() {
foo = 0;
foo += 1;
});
afterEach(function() {
foo = 0;
});
it("contains spec with an expectation", function() {
expect(true).toBe(true);
});
});
每個測試都在一個測試集中運行,Suite就是一個測試集,用describe函數封裝。 Spec表示每個測試用例,用it函數封裝。通過expect函數,作為程序斷言來判斷相等關系。setup過程用beforeEach函數封裝,tearDown過程用afterEach封裝。
3.Karma的安裝
3.1:系統環境:
win7 64bit, node v0.10.32, npm 1.4.28
3.2:開始安裝karma
E:\workspace npm install -g karma
注:-g代表全局安裝
3.4:測試是否安裝成功
E:\workspace karma start
打開瀏覽器訪問http:\\localhost:9876出現下面界面表示OK
4karma+jasmine+requirejs
4.1:初始化karma配置文件karma.conf.js
~ D:\workspace\javascript\karma>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.
> yes
注:需不需要引入requirejs
引入requirejs的原因:加載相互依賴的js文件
Do you want to capture a browser automatically ?
Press tab to list possible options. Enter empty string to move to the next question.
> 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.
>
注:karma啟動時加載的目標文件和測試文件
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
注:karma要不要動態監聽目標文件和測試用例變化
Config file generated at "D:\workspace\javascript\karma\karma.conf.js".
這個指令跑完后你就會發現目錄底下多了個配置文件karma.conf.js,test-main.js
karma.conf.js: karma配置文件
test-main.js: requireJS配置文件
4.2.Karma第一次啟動時的問題
1,chrome的plugins
~ E:\workspace npm install karma-chrome-launcher --save-dev
2,環境變量CHROM_BIN的問題
~ D:\workspace\javascript\karma>karma start
INFO [karma]: Karma v0.10.2 server started at http://localhost:9876/
INFO [launcher]: Starting browser Chrome
ERROR [launcher]: Cannot start Chrome
Can not find the binary C:\Users\Administrator\AppData\Local\Google\Chrome\Application\chrome.exe
Please set env variable CHROME_BIN
設置chrom的CHROM_BIN
~ E:\workspace Set CHROM_BIN= “C:/Program Files (x86)/Chrome/chrome.exe”
4.3.安裝集成包karma-jasmine
~ E:\workspace npm install karma-jasmine
4.4. Requirejs簡介
RequireJS是一個Javascript 文件和模塊框架,可以從 http://requirejs.org/下載,如果你使用Visual Studio也可以通過Nuget獲取。它支持瀏覽器和像node.js之類的服務器環境。使用RequireJS,你可以順序讀取僅需要相關依賴模塊。
RequireJS所做的是,在你使用script標簽加載你所定義的依賴時,將這些依賴通過head.appendChild()函數來加載他們。當依 賴加載以后,RequireJS計算出模塊定義的順序,並按正確的順序進行調用。這意味着你需要做的僅僅是使用一個“根”來讀取你需要的所有功能,然后剩下的事情只需要交給RequireJS就行了。為了正確的使用這些功能,你定義的所有模塊都需要使用RequireJS的API,否者它不會像期望的那樣 工作。
4.5.安裝集成包 requires
通過nodejs安裝RequireJS
~ E:\workspace npm install requires –save-dev
~ E:\workspace npm install karma-requires –save-dev
注:-save-dev : 可以直接 安裝的包自動添加到grunt包管理配置文件中
4.6. RequireJS配置
在一般的web項目中 require都是通過<sricpt>標簽靜態加載到項目中去的
例如:< sricpt data-main=”main.js” src=”require.js”></ sricpt >
注:RequireJS是怎么開始工作:當RequireJS被加載的時候,它會使用 data-main屬性去搜尋一個腳本文件(它應該是與使用src加載RequireJS是相同的腳本)。data-main需要給所有的腳本文件設置一 個根路徑。根據這個根路徑,RequireJS將會去加載所有相關的模塊。
Data-main:指向的requirejs的配置文件
配置test-main.js
// This file is test/spec/main.js
var allTestFiles = [];
var TEST_REGEXP = /(spec|test)\.js$/i;
var pathToModule = function(path) {
return path.replace(/^\/base\//, '').replace(/\.js$/, '');
};
Object.keys(window.__karma__.files).forEach(function(file) {
if (TEST_REGEXP.test(file)) {
// Normalize paths to RequireJS module names.
allTestFiles.push(pathToModule(file));
}
});
require.config({
// Karma serves files under /base, which is the basePath from your config file
baseUrl: 'base/src/js',
paths: {
'mootools' : ' lib/mootools',
'jquery' : 'lib/jquery-1.10.2',
'jquery-ui' : 'ib/jquery-1.10.2/jquery-ui'
},
shim: {
'jquery-ui': {
deps: ['jquery']
}
},
// dynamically load all test files
deps: allTestFiles,
// we have to kickoff jasmine, as it is asynchronous
callback: window.__karma__.start
});
再通過 karma 配置文件將其引入
files: [
{pattern: 'src/js/lib/*.js', included: false},
{pattern: 'src/js/apps/*.js', included: false},
{pattern: 'test/*-spec.js', included: false},
'test/*-spec.js',
‘test-main.js',
'src/*.js'
],
5.自動單元測試
5.1:三步准備工作:
創建源文件
源文件:用於實現某種業務邏輯的文件,就是我們平時寫的js腳本
假如我們的源文件原來有個需求有一個需求:要實現單詞倒寫的功能,如:”ABCD” ==> “DCBA”
Src/test.js
function reverse(name){
return name.split("").reverse().join("");
}
創建測試文件
測試文件:符合jasmineAPI的測試js腳本
Test/spec/module1/test-spec.js
describe("A suite of basic functions", function() {
it("reverse word",function(){
expect("DCBA").toEqual(reverse("ABCD"));
});
});
修改karma .conf.js
前期 自動生成的配置文件比較凌亂,而且有好多地方配置不到位,這個時候大家可以地下的代碼 替換其內容
module.exports = function(config) {
config.set({
// base path, that will be used to resolve files and exclude
basePath: '',
// frameworks to use
frameworks: ['jasmine', 'requirejs'],
// list of files / patterns to load in the browser
files: [
{pattern: 'src/js/apps/inspect/*.js', included: false},
{pattern: 'src/js/modules/*.js', included: false},
{pattern: 'src/js/lib/*.js', included: false},
{pattern: 'src/js/apps/settings/*.js', included: false},
{pattern: 'test/spec/**/*-spec.js', included: false},
'test-main.js'
],
preprocessors: {
'src/js/apps/inspect/*.js': ['coverage']
},
// list of files to exclude
exclude: [],
// test results reporter to use
// possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'
reporters: ['progress', 'coverage'],
coverageReporter: {
type: 'html',
dir: 'coverage/'
},
// 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, currently available:
// - Chrome
// - ChromeCanary
// - Firefox
// - Opera (has to be installed with `npm install karma-opera-launcher`)
// - Safari (only Mac; has to be installed with `npm install karma-safari-launcher`)
// - PhantomJS
// - IE (only Windows; has to be installed with `npm install karma-ie-launcher`)
browsers: ['Chrome'],
// If browser does not capture in given timeout [ms], kill it
captureTimeout: 60000,
// Continuous Integration mode
// if true, it capture browsers, run tests and exit
singleRun: false
});
};
5.2.測試requireJS
1.將前面的test.js剪切至src/js/apps/inspect/
2.修改karma配置文件引入路徑
3. 運行karma start會出現下面的結果
6.Karma統計UT覆蓋率輸出報告
~ E:\workspace npm install karma-coverage
注:打完指令如果細心觀察你就會發現karma的配置文件中多了藍色部分代碼,是對UT覆蓋率輸出的配置。
module.exports = function(config) {
config.set({
// base path, that will be used to resolve files and exclude
basePath: '',
// frameworks to use
frameworks: ['jasmine', 'requirejs'],
// list of files / patterns to load in the browser
files: [
{pattern: 'src/js/apps/inspect/*.js', included: false},
{pattern: 'src/js/modules/*.js', included: false},
{pattern: 'src/js/lib/*.js', included: false},
{pattern: 'src/js/apps/settings/*.js', included: false},
{pattern: 'test/spec/**/*-spec.js', included: false},
'test-main.js'
],
preprocessors: {
'src/js/apps/inspect/*.js': ['coverage']
},
// list of files to exclude
exclude: [],
// test results reporter to use
// possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'
reporters: ['progress', 'coverage'],
coverageReporter: {
type: 'html',
dir: 'coverage/'
},
// 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, currently available:
// - Chrome
// - ChromeCanary
// - Firefox
// - Opera (has to be installed with `npm install karma-opera-launcher`)
// - Safari (only Mac; has to be installed with `npm install karma-safari-launcher`)
// - PhantomJS
// - IE (only Windows; has to be installed with `npm install karma-ie-launcher`)
browsers: ['Chrome'],
// If browser does not capture in given timeout [ms], kill it
captureTimeout: 60000,
// Continuous Integration mode
// if true, it capture browsers, run tests and exit
singleRun: false
});
};啟動karma start,在工程目錄下面找到index.html文件,coverage/chrome/index.html
打開后,我們看到代碼測試覆蓋綠報告
點擊文件路徑進入文件夾點擊文件可以此文件的UT覆蓋率
有顏色的文件代表未覆蓋到的文件(覆蓋由好到壞顯示顯色綠,黃,紅)
7 grunt 托管karma
7.1.Grunt 簡介
Grunt是一個自動化的項目構建工具. 如果你需要重復的執行像壓縮, 編譯, 單元測試, 代碼檢查以及打包發布的任務. 那么你可以使用Grunt來處理這些任務, 你所需要做的只是配置好Grunt, 這樣能很大程度的簡化你的工作.
如果在團隊中使用Grunt, 你只需要與其他人員約定好使用Grunt應該規避的問題, 就能夠很方便的自動化的處理大部分的常見工作任務, 你所付出的努力幾乎為0.
7.2.任務配置修改
Install grunt-karma
使用install grunt-karma –save-dev將 grunt-karma載入grunt包管理配置文件Gruntfile.js
Gruntfile.js中增加配置
注:任務配置
karma: {
unit: {
configFile: "karma.conf.js",
singleRun: true
}
},
注:載入模塊文件
grunt.loadNpmTasks('grunt-karma');
注:定義具體的任務。第一個參數為任務名,第二個參數是一個數組,表示該任務需要依次使用的模塊。default任務名表示,如果直接輸入grunt命令,后面不跟任何參數,這時所調用的模塊(該例為jshint,concat和uglify)
grunt.registerTask('unit', [‘jshint’, ‘concat’, ‘uglify’]);
grunt.registerTask('unit', ['karma']);
