以上一篇文章《测试笔记 (二) sinon and nock》的文件结构为基础。
1, 写一个angular小程序
bower init
bower install angular angular-ui-router --save //安装angular及路由
mkdir client //作为angular应用目录
mkdir test_karma //作为测试文件目录
client 文件夹结构如下:
client ---
index.html
app ---
index.js
main.html
文件内容分别如下:
/**client/index.html**/
<!DOCTYPE html>
<html ng-app="testexample">
<head>
<title>Angular 测试</title>
</head>
<body>
<div ui-view></div>
<script src="angular/angular.js"></script>
<script src="angular-ui-router/release/angular-ui-router.js"></script>
<script src="app/index.js"></script>
</body>
</html>
/**client/app/index.js**/
(function () {
'use strict';
angular.module('testexample', ['ui.router'])
.config(function ($stateProvider,$urlRouterProvider) {
$stateProvider
.state('main', {
url: '/',
templateUrl: 'app/main.html',
controller: 'MainCtrl'
});
$urlRouterProvider.otherwise('/');
})
.controller('MainCtrl',function ($scope,$http) {
$scope.name = 'Jack Hu';
$http.get('/articleList').success(function (data, status) {
$scope.articleList = data;
}).error(function (err, status) {
$scope.articleList = [];
});
});
})();
/***client/app/main.html**/
<div ng-repeat="article in articleList">
<p>{{article.id}}</p>
<p>{{article.title}}</p>
<p>{{article.content}}</p>
<hr>
</div>
修改一下根目录下的app.js,让ng小程序跑起来.
//var app = express(); 之后增加
app.use(express.static(__dirname + '/client'));
app.use(express.static(__dirname + '/bower_components'));
//app.listen.... 之前增加
app.get('/',function (req,res) {
return res.sendFile('index.html',{root:__dirname + '/client'});
});
node app.js 运行程序,在浏览器输入http://localhost:3000
看到如下画面即成功
2, 配置karma
npm i -g karma-cli //全局安装karma
npm i karma karma-jasmine karma-chrome-launcher --save-dev //安装karma及jasmine(不用再单独安装jasmine)
npm i karma-angular-filesort karma-ng-html2js-preprocessor karma-coverage --save-dev //安装angular相关插件及测试覆盖率插件
安装angular测试必装angular-mocks
bower install angular-mocks --save-dev
初始化配置
karma init //有提示时全部回车
这样在根目录下生成一个karma.conf.js的配置文件. 对配置文件做相应修改,如下:
// Karma configuration
module.exports = function(config) {
config.set({
// 根路径,其它相对路径都这它为基准
basePath: '',
//使用的测试框架
frameworks: ['jasmine'],
//所有浏览器加载的文件路径
files: [
'bower_components/angular/angular.js',
'bower_components/angular-ui-router/release/angular-ui-router.js',
'bower_components/angular-mocks/angular-mocks.js',
'client/**/*.js',
'client/**/*.html',
'test_karma/**/*.spec.js'
],
//对angular文件按照依赖注入顺序加载
angularFilesort: {
whitelist: [
'client/**/*.js'
]
},
// 需要排除的文件
exclude: [
],
//预处理器,默认只对CoffeeScript预处理,其它的需要装插件,这里对应两个插件
preprocessors: {
'client/**/*.js': ['coverage'], //测试覆盖率插件karma-coverage
'client/**/*.html': ['ng-html2js'] //将angular模板文件转化成$templatecache
},
//默认module名称为templates
ngHtml2JsPreprocessor: {
stripPrefix: 'client/',
moduleName: 'templates'
},
//测试结果报告,默认只有progress,其它的需要手动添加.
reporters: ['progress','coverage'],
//测试覆盖率配置,text-summary在控制台打印, html 生成html文件到指定的dir
coverageReporter: {
//type : 'html',
type:'text-summary',
dir : 'test_karma_coverage/'
},
//默认端口
port: 9876,
// 开启关闭有颜色的输出
colors: true,
// 输出的日志级别
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// 是否开启自动监控
autoWatch: false,
// 运行测试的浏览器,需要安装插件
browsers: ['Chrome'],
// 是否只运行一次就退出karma, 通常和autoWatch配合使用,当autoWatch为true时,此处为false
singleRun: true
})
}
3,添加测试文件 test_karma/main.spec.js
'use strict';
describe('module testexample', function() {
beforeEach(module('testexample'));
beforeEach(module('templates'));
});
先不添加控制器的测试, 运行 karma start 看模块是否正常加载.
如果配置文件不是karma.conf.js,则需要指定配置文件如: karma start my.conf.js
运行测试会弹出浏览器, 如果配置singleRun:true 浏览器会自动关闭.
如果没有报错,说明模块加载正常,接下我们对MainCtrl控制器进行测试.
'use strict';
describe('module testexample', function() {
beforeEach(module('testexample'));
beforeEach(module('templates'));
describe('main controller', function() {
var $scope,MainCtrl;
beforeEach(inject(function (_$controller_,_$rootScope_) {
$scope = _$rootScope_.$new();
MainCtrl = _$controller_('MainCtrl',{$scope:$scope});
}));
it('should return my name',function () {
expect($scope.name).toBe('Jack Hu');
});
});
});
Jasmine 提供了全局的 beforeEach 和 afterEach 方法。正像其名字一样,beforeEach 方法在 describe 中的每个 Spec 执行之前运行,afterEach 在每个 Spec 调用后运行。
在Spec之前需要注入$scop, 测试name是否匹配.
再次运行karma start 结果如图所示,有1个测试通过,并显示覆盖率.
4, $http测试
主要是对$httpbacked有所了解, 它可以设置假的后台,测试的时候,我们不需要真实的发送HTTP请求来获取数据。只测试Service的逻辑,当发送请求时,我们将这个请求拦截下来,然后返回一个预定义好的数据.
$httpbacked有两种写法: 第一种: $httpBackend.expect 第二种: $httpBackend.when 区别在于$httpBackend.expect只被调用一次就被清除,第二次调用会出错.
$httpBackend.flush() ---- 立即执行完成所有定义的http请求.
$httpBackend.verifyNoOutstandingExpectation() ---- 如果我们使用了$httpBackend.expect的话,而没有相应的request请求,最后在这个测试用例结束后,就会有个异常报错(Unsatisfied requests)提醒您有涉及的后台没有请求到。
$httpBackend.verifyNoOutstandingRequest() ---- $httpBackend.expect如果request请求了但是没有执行$httpBackend.flush,afterEach中设置了$httpBackend.verifyNoOutstandingRequest()就会异常报错(Unflushed requests)
$httpBackend.resetExpectations() ---- $httpBackend.resetExpectations可以移除所有的expect而对$httpBackend.when没有影响。
'use strict';
describe('module testexample', function() {
beforeEach(module('testexample'));
beforeEach(module('templates'));
describe('main controller', function() {
var $scope,MainCtrl,$httpBackend,mockArticleList;
beforeEach(inject(function (_$rootScope_,_$controller_,_$httpBackend_) {
$httpBackend = _$httpBackend_;
$scope = _$rootScope_.$new();
MainCtrl = _$controller_('MainCtrl',{$scope:$scope});
mockArticleList = $httpBackend.when('GET','/articleList').respond([
{
"id":"10001",
"title":"中国世界第一",
"content":"人均也是第一"
},{
"id":"10002",
"title":"中国程序员万岁",
"content":"中国程序员万岁万岁万万岁!"
}
]);
}));
afterEach(function () {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
it('should return my name',function () {
expect($scope.name).toBe('Jack Hu');
expect($scope.articleList).toBeFalsy();
$httpBackend.flush();
expect($scope.articleList.length).toEqual(2);
});
});
});
运行测试karma start 测试通过.
在$httpBackend.flush()之前$scope.articleList是不存在的.而之后已成功获取.
本文测试样例下载地址: https://github.com/jackhutu/test-example/tree/angular-karma-jasmine
angular还活着
~~~
???
????
464
keyi a .
666
2222
2222sssssssss
<script type="text/javascript">alert('傻逼!');</script>
php是世界上最好的语言