测试笔记 (三) angular测试(karma + jasmine)

阅读4168评论10

一, 简介

  1. Karma 是由google出品的一个基于Node.js 的 JavaScript 测试执行过程管理工具(Test Runner), 它可以让你的js代码运行在多个真实的浏览器.无测试框架限制,有监控文件的功能.
  2. Jasmine 是一个基于JS的行为驱动开发测试框架.它不依赖于其它任何js框架,也不需要对DOM。
  3. Angular-mocks 为angular单元测试提供模块定义、加载、注入等支持。辅助Karma、Jasmine等JS测试工具来模拟angular方法,测试angular应用。除此之外,Angular-mock还扩展了ng的多个核心服务,使之可以被测试代码以同步的方式进行审查和控制。

二, 准备

以上一篇文章《测试笔记 (二) 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
看到如下画面即成功
enter image description here

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个测试通过,并显示覆盖率. test result

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

10条评论添加新评论
JackJack2016.3.17 1:8

angular还活着

huangliangchina@Jack er

huangliangchina@Jack ni

同王园同王园2016.9.2 2:15

~~~

孙振宇孙振宇2017.3.17 2:10

???

孙振宇孙振宇2017.3.17 2:11

????

fredanyfredany2017.6.29 15:17

464

lzfei@fredany ss

lzfeilzfei2017.9.27 8:50

keyi a .

huangliangchina@lzfei sdfsasadf

哈哈哈蜜瓜哈哈哈蜜瓜2017.10.11 2:0

666

huangliangchina@哈哈哈蜜瓜 ddddddddddddddd

huanglianghuangliang2017.12.7 15:45

2222

huanglianghuangliang2017.12.7 15:46

2222sssssssss

share0307share03072018.7.13 3:51

&lt;script type="text/javascript"&gt;alert('傻逼!');&lt;/script&gt;