因为项目要求,需要对一个angularjs项目进行单元测试,所以就去简单学习了一下,主要利用Karma和Jasmine来进行ng模块的单元测试。
介绍
Karma
Karma是一个基于Node.js的JavaScript测试执行过程管理工具(Test Runner)。该工具可用于测试所有主流Web浏览器,也可集成到CI(Continuous integration)工具,也可和其他代码编辑器一起使用。这个测试工具的一个强大特性就是它可以监控文件的变化,然后自动执行,通过console.log显示测试结果。
Jasmine
Jasmine是一个用域JS代码测试的行为驱动开发的框架,它不依赖于任何其他的JS框架以及DOM,是一个简洁及友好的API测试库。
安装
在Karma的官方文档中,介绍的有安装方法。
首先你的电脑上需要安装的有Node.js,目前支持的Node.js版本有6.x, 8.x, 10.x。
# Install Karma:
$ npm install karma --save-dev
# Install plugins that your project needs:
$ npm install karma-jasmine karma-chrome-launcher jasmine-core --save-dev
安装成功后,这些模块会保存在你的项目里的package.json文件的devDependencies属性里。
# Run Karma:
$ ./node_modules/karma/bin/karma start
因为是局部安装,所以需要进入到安装目录下面执行,当然我们也可以全局安装,这样使用起来可能更方便一些。
$ npm install -g karma-cli
配置
在项目根目录下,执行
$ karma init my.conf.js
当然,配置文件的名字可以随意更改,命令执行的时候会询问一些问题,一般使用默认配置就好。执行完之后会生成一个my.conf.js文件,文件内容如下:
// Karma configuration
// Generated on Mon Nov 12 2018 16:11:21 GMT+0800 (中国标准时间)
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: [
],
// list of files / patterns to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
},
// 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,
// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity
})
}
# Start Karma using your configuration:
$ karma start my.conf.js
执行上述命令会自动打开一个浏览器,可以用来Debug。
Karma
至此,我们测试环境已经配置好了,下面结合具体项目来进行测试。
实例
准备
因为angularjs是通过依赖注入的方式来加载以及实例化的,所以为了方便配合jasmine来编写测试脚本,官方提供了angular-mock来提供模块定义,加载,注入等。所以还需要安装一下angular-mocks,我的项目目录如下,因为我的Karma是全局安装的,所以没有node_modules文件。
项目目录
可以看到我需要测试的文件是index.js,测试用例在spec目录下,对应的是index.spec.js。
接下来我们结合项目更改一下Karma配置文件,把依赖和待测试文件放到files数组中。
// list of files / patterns to load in the browser
files: [
'./bower_components/angular/angular.js',
'./bower_components/angular-mocks/angular-mocks.js',
'./src/js/*.js',
'./src/spec/*[sS]pec.js'
]
index.js内容如下,包括controller, services, directive和filter:
var app = angular.module('myApp', []);
app.controller('myAppController', ['$scope', 'myService', function($scope, myService) {
$scope.count = 0;
$scope.add = function() {
$scope.count ++;
};
$scope.reset = function() {
$scope.count = 0;
};
$scope.get = function () {
myService.getData().then(function (res) {
$scope.data = res.data;
})
}
}]);
app.service('myService', ['$http', function ($http) {
return {
getData: getData
}
function getData() {
return $http.get("http://rapapi.org/mockjsdata/29387/getCartList");
}
}])
app.directive('currentDate', function() {
return {
restrict: 'E',
replace: 'false',
template: `<h4 style="margin: 100px auto">${new Date().getFullYear()}</h4>`
}
});
app.filter('percentage', function() {
return function(num) {
if (num == null) {
return '0%';
} else {
return (parseFloat(num) * 100).toFixed(0) + '%';
}
};
});
index.spec.js文件,包括对controller,services,directive和filter的测试,代码中都标有注释,就不详细说了:
describe('myApp', function() {
// 引入模块
beforeEach(module('myApp'));
// 测试controller
describe('test controller', function () {
var scope, ctrl;
beforeEach(inject(function($rootScope, $controller) {
// scope是rootScope new出来的
scope = $rootScope.$new();
ctrl = $controller('myAppController', {$scope: scope});
}));
it('addFunction', inject(function() {
expect(scope.count).toEqual(0);
scope.add();
expect(scope.count).toEqual(1);
}));
it('resetFunction', inject(function () {
scope.reset();
expect(scope.count).toEqual(0);
}));
// 测试services
it('getFunction', inject(function ($injector) {
// $httpBackend 是由angular mock提供的一个模拟http请求返回服务
// 可以用它来模拟http请求的返回值
// 这里通过$injector来获取它的实例
var $httpBackend = $injector.get('$httpBackend');
$httpBackend.when('GET', 'http://rapapi.org/mockjsdata/29387/getCartList').respond({
age: '18',
name: 'tina'
})
scope.get();
//把http的异步转为同步,要求$httpBackend立刻返回数据
$httpBackend.flush();
expect(scope.data).toEqual({
age: '18',
name: 'tina'
});
}))
})
// 测试过滤器
describe('test filter', function() {
it("should return 60", inject(function (percentageFilter) {
expect(percentageFilter(0.6)).toBe('60%');
}))
})
// 测试指令
describe('test directive', function() {
it("should get 2018", inject(function ($compile, $rootScope) {
scope = $rootScope.$new();
// 调用指令
elem = angular.element('<current-date></current-date>');
// 编译
$compile(elem)(scope);
console.log(elem.html());
expect(elem.html()).toEqual('2018')
}))
})
});
至于测试用例怎么书写就不详细介绍了,可参考文档,也可参考博客。
执行
在package.json文件中添加
"scripts": {
"test": "karma start karma.config.js"
}
终端输入
npm test
效果如下:
效果
网友评论