介绍
使用 karma + Jasmine,就可以测试指定的案例, 加入RequireJS, 可以进行测试异步模块的案例
安装
# Install Karma:
$ npm install karma --save-dev
# Install plugins that your project needs:
$ npm install karma-jasmine karma-chrome-launcher jasmine-core --save-dev
# Install karma-requirejs
$ npm install requirejs --save-dev
$ npm install karma-requirejs --save-dev
全局配置karma 命令行
npm install -g karma-client
配置
module.exports = function (config) {
config.set({
// ...
frameworks: ['jasmine', 'requirejs'],
files: [
{pattern: 'lib/**/*.js', included: false},
{pattern: 'src/**/*.js', included: false},
{pattern: 'test/**/*[sS]pec.js', included: false},
'test-main.js'
]
// ...
})
}
加载karma-jasmine
, karma-requirejs
框架, 引入 test-main.js
. files
。
test-main.js
介绍
var allTestFiles = []
// 测试文件
var TEST_REGEXP = /(spec|test)\.js$/i
// Get a list of all the test files to include
// 解析files 和 frameworks 对应需要加载的文件
Object.keys(window.__karma__.files).forEach(function (file) {
if (TEST_REGEXP.test(file)) {
// Normalize paths to RequireJS module names.
// If you require sub-dependencies of test files to be loaded
// as-is (requiring file extension)
// then do not normalize the paths
// 将符合条件的测试文件转化为 requirejs 能加载的模块名
var normalizedTestModule = file.replace(/^\/base\/|\.js$/g, '')
allTestFiles.push(normalizedTestModule)
}
})
require.config({
// Karma serves files under /base, which is the basePath from your config file
// karma 将basePath 对应的静态路径设置为 /base
// requirejs 加载文件也应当由 /base 开始
baseUrl: '/base',
// dynamically load all test files
// 动态加载测试文件
deps: allTestFiles,
// we have to kickoff jasmine, as it is asynchronous
// deps 加载完后 执行 单元测试
callback: window.__karma__.start
})
简单demo
目录结构
- test
- src
- lib
- test-main.js
- index.html
- main.js
源文件 src/utils/qs.js
define(function () {
var encodeURIComponent = window.encodeURIComponent;
var decodeURIComponent = window.decodeURIComponent;
function isArray (o) {
return Object.prototype.toString.call(o) === '[object Array]';
}
function isObject (o) {
return Object.prototype.toString.call(o) === '[object Object]';
}
return {
parse: function (url) {
if (typeof url !== 'string') {
throw new TypeError('qs.parse() Error, url should transmit a string param');
}
var result = {};
url = url.substr(url.indexOf('?') + 1);
var querystring = url.replace(/#.*/, '');
var patterns = querystring.split('&');
patterns.forEach(function(pattern) {
if (!pattern) {
return;
}
var matched = pattern.match(/([^=]+)=(.*)/);
if (!matched) {
return;
}
var key = matched[1],
value = matched[2],
isArr = false;
if (key.slice(-2) === '[]') {
key = key.slice(0, -2);
isArr = true;
}
key = decodeURIComponent(key);
value = decodeURIComponent(value);
if (isArr) {
if (!Array.isArray(result[key])) {
result[key] = [];
}
result[key].push(value);
} else {
result[key] = value;
}
}, this);
return result;
},
stringify: function (obj) {
if (!isObject(obj)) {
throw new TypeError('qs.stringify() Error, Unexpected obj is not Object');
}
return Object.keys(obj).map(function (name, index) {
if (isArray(obj[name])) {
return obj[name].map(function (item) {
return encodeURIComponent(name) + '[]=' + encodeURIComponent(item);
}).join('&');
}
return encodeURIComponent(name) + '=' + encodeURIComponent(obj[name]);
}).join('&');
}
}
});
测试文件 test/utils/qsSpec.js
define(['src/utils/qs'], function(qs) {
beforeAll(function () {
spyOn(qs, 'parse').and.callThrough();
spyOn(qs, 'stringify').and.callThrough();
});
describe('qs.parse() suite', function() {
it('should throw TypeError', function() {
expect(qs.parse).toThrowError(TypeError);
});
it('should parse to object', function () {
var url = 'http://liylblog.com/?a=1&b=2&c=3';
expect(qs.parse(url)).toEqual({
a: '1',
b: '2',
c: '3'
});
});
it('should parse to object array', function () {
var url = 'http://liylblog.com/?a[]=1&a[]=2&a[]=3';
expect(qs.parse(url)).toEqual({
a: ['1', '2', '3']
});
});
it('should be decodeURIComponent', function () {
var aVal = window.encodeURIComponent('=1');
var bVal = window.encodeURIComponent('?2');
var url = 'http://liylblog.com/?a=' + aVal + '&b=' + bVal + '&c=3#';
expect(qs.parse(url)).toEqual({
a: '=1',
b: '?2',
c: '3'
});
});
});
describe('qs.stringify() suite', function () {
var obj;
beforeEach(function () {
obj = {
a: 1,
b: ['你好', '世界'],
c: ['2', null, '']
};
});
afterEach(function () {
obj = null;
});
it('should throw TypeError', function() {
expect(qs.stringify).toThrowError(TypeError);
});
it('should stringify obj', function () {
var querystring = qs.stringify(obj);
var containB = (function () {
var str = ''
for (var i = 0, len = obj['b'].length; i < len; i++) {
str += i > 0 ? '&' : ''
str += 'b[]=' + encodeURIComponent(obj['b'][i])
}
return str;
})();
var containC = 'c[]=null';
expect(querystring).toContain('a=1')
expect(querystring).toContain(containB);
expect(querystring).toContain(containC);
});
});
});
执行
karma start ./karma.conf.js