karma作為angular測試runner出現,如果你使用過karma一定感受到這很不錯的javascript測試runner。簡單干凈的配置文件karma.config.js,以及karma init一些快捷的配置command。以及整套測試套件,如html2js,coverage。對於angular單元測試karma就是一個全生態的測試套件,能夠簡潔快速的搭建整個測試流程。
本文將嘗試運用karma作為jQuery單元測試runner。對於jQuery這種DOM操作的框架,有時難於分離view邏輯,以及ajax這種外部資源的mock,所以比較難於實施對jQuery程序的TDD開發。
jasmime測試套件
對於jasmine測試框架為了解決這些問題有兩個插件jasmine-jquery和jasmine-ajax。
jasmine-jquery
jasmine-jQuery主要解決加載測試所需的DOM元素,為單元測試構建前置環境。jasmine-jQuery加載DOM方法:
jasmine.getFixtures().fixturesPath = 'base path'; loadFixtures('myfixture.html'); jasmine.getFixtures().load(...);
這里的loadFixtures需要真實ajax獲取html fixtures所以我們需要提前host html fixtures。jasmine-jQuery還框架了一些有用的matchers,如toBeChecked, toBeDisabled, toBeFocused,toBeInDOM……
jasmine-ajax
jasmine-ajax則是對於一般ajax測試的mock框架,其從底層xmlhttprequest實施mock。所以讓我們能很容易實施對於jQuery的$.ajax,$.get…mock。如
beforeEach(function() { jasmine.Ajax.requests.when = function (url) { return this.filter("/jquery/ajax")[0]; }; jasmine.Ajax.install(); }); it("jquery ajax success with getResponse", function() { var result; $.get("/jquery/ajax").success(function(data) { result = data; }); jasmine.Ajax.requests.when("/jquery/ajax").response({ "status": 200, "contentType": 'text/plain', "responseText": 'data from mock ajax' }); expect(result).toEqual('data from mock ajax'); }); afterEach(function() { jasmine.Ajax.uninstall(); });
對於jasmine-ajax是實施mock之前一定需要jasmine.Ajax.install(),以及測試完成后需要jasmine.Ajax.uninstall();jasmine-ajax在install后會把所有的ajax mock掉,所以如果有需要真實ajax的需要在install之前完成,如jasmine-jQuery加載view loadFixtures。
運用karma runner
我們已經了解了jasmine測試的兩個框架jasmine-jQuery和jasmine-ajax,所以運用karma作為runner,我們需要解決的問題就是把他們和karma集成在一起。
所以分為以下幾步: 1:karma中引入jasmine-jQuery和jasmine-ajax(可以利用bowerinstall) 2:host 測試的html fixtures。 3:加載html fixtures 與install ajax之前。
對於host 文件karma提供了pattern模式,所以karma配置為:
files: [ { pattern: 'view/**/*.html', watched: true, included: false, served: true }, 'bower_components/jquery/dist/jquery.js', 'bower_components/jasmine-jquery/lib/jasmine-jquery.js', 'bower_components/jasmine-ajax/lib/mock-ajax.js', 'src/*.js', 'test/*.js' ],
這里需要注意karma自帶的jasmine是低版本的,所以我們需要npm install karma-jasmine@2.0獲取最新的karma-jasmine插件。
我們就可以完成了karma的配置,我們可以簡單測試我們的配置:demo on github.
測試html fixtures加載:
describe('console html content', function() {
beforeEach(function() {
jasmine.getFixtures().fixturesPath = 'base/view/';
loadFixtures("index.html");
});
it('index html', function() {
expect($("h2")).toBeInDOM();
expect($("h2")).toContainText("this is index page");
});
})
測試mock ajax:
describe('console html content', function() {
beforeEach(function() {
jasmine.Ajax.requests.when = function(url) {
return this.filter("/jquery/ajax")[0];
};
jasmine.Ajax.install();
});
it('index html', function() {
expect($("h2")).toBeInDOM();
expect($("h2")).toContainText("this is index page");
});
it("ajax mock", function() {
var doneFn = jasmine.createSpy("success");
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(args) {
if (this.readyState == this.DONE) {
doneFn(this.responseText);
}
};
xhr.open("GET", "/some/cool/url");
xhr.send();
expect(jasmine.Ajax.requests.mostRecent().url).toBe('/some/cool/url');
expect(doneFn).not.toHaveBeenCalled();
jasmine.Ajax.requests.mostRecent().response({
"status": 200,
"contentType": 'text/plain',
"responseText": 'awesome response'
});
expect(doneFn).toHaveBeenCalledWith('awesome response');
});
it("jquery ajax success with getResponse", function() {
var result;
getResponse().then(function(data){
result = data;
});
jasmine.Ajax.requests.when("/jquery/ajax").response({
"status": 200,
"contentType": 'text/plain',
"responseText": 'data from mock ajax'
});
expect(result).toEqual('data from mock ajax');
});
it("jquery ajax error", function() {
var status;
$.get("/jquery/ajax").error(function(response) {
status = response.status;
});
jasmine.Ajax.requests.when("/jquery/ajax").response({
"status": 400
});
expect(status).toEqual(400);
});
afterEach(function() {
jasmine.Ajax.uninstall();
});
})
更多請參見demo on github.
