angularJS+requireJS并集成karma测试实践

最近在为下一个项目做前端技术选型,Angular是必须要用的(BOSS指定,个人感觉也不错,开发效率会很高)。由于需要加载的JS很多,所以打算看看angular和requirejs一起用会怎么样。在git上有一个模板加《angular-requirejs-seed》,这个对angular和requirejs结合有很好的指导。但是他把karma的单元测试js放在项目中了,我更喜欢放在test目录下。

由于为linux下没有截图工具,就手打了。求Linux下好用的截图工具分享。要用karma测试首先使用karma init命令生成测试文件karma.conf.js。

在项目下输入命令karma init  

  Which testing framework do you want to use? jasmine  

  Do you want to use Require.js?  yes            注意:按上下键就可以选择

  Do you want to capture any browsers automatically?   Chrome  注意,可以选多个

  What is the location of your source and test files?  app/**/**/*.js  enter键  app/app.js  enter键  app/require-config.js  enter键 test/**/*Spec.js    这里的路径更加实际项目情况来确定。可以多个路径。

  Should any of the files included by the previous patterns be excluded ? enter键跳过。

  Do you wanna  generate a bootstrap file for RequireJS? yes

  Do you want karma to watch all the files and run the tests on change? yes

 在这些步骤完成之后,会在根目录生成叫做karma.conf.js和test-main.js的两个文件。由于习惯,我喜欢将karma.conf.js放入test目录下,这时需要将karma.conf.js的basePath改为"..";这里的test-main.js文件就是karma在测试的代替app下的require-config.js的文件,所以test-main.js文件和require-config的内容几乎完全一样,只是由于位置不一样,所以在test-main中增加一个baseUrl.

 1 var allTestFiles = [];
 2 var TEST_REGEXP = /(spec|test)\.js$/i;
 3 
 4 Object.keys(window.__karma__.files).forEach(function(file) {
 5   if (TEST_REGEXP.test(file)) {
 6     // Normalize paths to RequireJS module names.
 7     allTestFiles.push(file);
 8   }
 9 });
10 
11 require.config({
12   // Karma serves files under /base, which is the basePath from your config file
13   baseUrl: '/base/app',
14   paths: {
15     angular: 'bower_components/angular/angular',
16     angularRoute: 'bower_components/angular-route/angular-route',
17     angularMocks: 'bower_components/angular-mocks/angular-mocks',
18     angularCookies:'bower_components/angular-cookies/angular-cookies',
19     angularResource:'bower_components/angular-resource/angular-resource'
20   },
21   shim: {
22     'angular' : {'exports' : 'angular'},
23     'angularRoute': ['angular'],
24     'angularCookies': ['angular'],
25     'angularResource': ['angular'],
26     'angularMocks': {
27       deps:['angular'],
28       'exports':'angular.mock'
29     }
30   },
31   priority: [
32     "angular"
33   ],
34   // dynamically load all test files
35   deps: allTestFiles,
36 
37   // we have to kickoff jasmine, as it is asynchronous
38   callback: window.__karma__.start
39 });
40 require([
41     'angular',
42     'app'
43   ], function(angular, app) {
44     var $html = angular.element(document.getElementsByTagName('html')[0]);
45     angular.element().ready(function() {
46       // bootstrap the app manually
47       angular.bootstrap(document, ['cxriaApp']);
48     });
49   }
50 );
test-main.js

 

 1 'use strict';
 2 
 3 if(window.__karma__) {
 4     var allTestFiles = [];
 5     var TEST_REGEXP = /spec\.js$/;
 6 
 7     var pathToModule = function(path) {
 8         return path.replace(/^\/base\/app\//, '').replace(/\.js$/, '');
 9     };
10 
11     Object.keys(window.__karma__.files).forEach(function(file) {
12         if (TEST_REGEXP.test(file)) {
13             // Normalize paths to RequireJS module names.
14             allTestFiles.push(pathToModule(file));
15         }
16     });
17 }
18 
19 require.config({
20     paths: {
21         angular: 'bower_components/angular/angular',
22         angularRoute: 'bower_components/angular-route/angular-route',
23         angularMocks: 'bower_components/angular-mocks/angular-mocks',
24     angularCookies:'bower_components/angular-cookies/angular-cookies',
25     angularResource:'bower_components/angular-resource/angular-resource',
26     uiBootstrap:'bower_components/angular-bootstrap/ui-bootstrap'
27     },
28     shim: {
29         'angular' : {'exports' : 'angular'},
30         'angularRoute': ['angular'],
31         'angularCookies': ['angular'],
32         'angularResource': ['angular'],
33         'angularMocks': {
34             deps:['angular'],
35             'exports':'angular.mock'
36         }
37     },
38     priority: [
39         "angular"
40     ],
41     deps: window.__karma__ ? allTestFiles : [],
42     callback: window.__karma__ ? window.__karma__.start : null,
43     baseUrl: window.__karma__ ? '../app' : ''
44 });
45 
46 require([
47     'angular',
48     'app'
49     ], function(angular, app) {
50         var $html = angular.element(document.getElementsByTagName('html')[0]);
51         angular.element().ready(function() {
52             // bootstrap the app manually
53             angular.bootstrap(document, ['cxriaApp']);
54         });
55     }
56 );
require-config

下面是为测试路由的代码:

 1 /**
 2  * Created by taox on 15-6-19.
 3  */
 4 'use strict';
 5 
 6 define([
 7   'angular',
 8   'angularMocks',
 9   'app'
10 ], function() {
11   describe('Routes test', function() {
12     var location,route,rootScope;
13     beforeEach(module('cxriaApp'));
14     beforeEach(inject(function(_$location_,_$route_,_$rootScope_){
15       location = _$location_;
16       route = _$route_;
17       rootScope = _$rootScope_;
18     }));
19     describe('index route', function(){
20       var httpbackend;
21       beforeEach(inject(function($httpBackend){
22         httpbackend = $httpBackend;
23       }));
24       it('should load the homepage on successful load of /.', inject(function() {
25         httpbackend.expectGET('./partials/home/home.html').respond('200','main HTML');
26         location.path('/');
27         rootScope.$digest();
28         expect(route.current.controller).toBe('HomeCtrl');
29       }));
30       it('should redirect to the homepage on non-existent route',function(){
31         httpbackend.expectGET('./partials/home/home.html').respond('200','main HTML');
32         location.path('/non-existent-path');
33         rootScope.$digest();
34         expect(route.current.controller).toBe('HomeCtrl');
35       });
36       it('should redirect to room page on successful load of /room/1',function(){
37         httpbackend.expectGET('./partials/room/room.html').respond('200','main HTML');
38         location.path('/room/1');
39         rootScope.$digest();
40         expect(route.current.controller).toBe('RoomCtrl');
41       })
42     });
43   });
44 
45 });
RouteSpec

对于karma再测试angular的指令时,为现在遇到一个很蛋疼的问题,那就时在当指令使用templateUrl时,需要karma-ng-html2js-preprocessor才能测试,这时需要修改karma.conf.js.

1.在files中增加模板的地址如:'app/directives/chatroom/*.html',

2.在plugins中增加''karma-ng-html2js-preprocessor',

3.在preprocessors中增加'app/directives/chatroom/*.html':['ng-html2js']

在这3步完成后,下面是我的测试文件,也通过测试了。

 1 /**
 2  * Created by taox on 15-6-30.
 3  */
 4 describe('Unit:Directives',function(){
 5   var scope,compile;
 6 
 7   beforeEach(module('chatroomDirective'));
 8   beforeEach(module('directives/chatroom/chatroom.html'));
 9   beforeEach(inject(function($compile,$rootScope){
10     compile = $compile;
11     scope = $rootScope;
12   }));
13 
14   it('should content words 发送',function(){
15     var ele = angular.element('<chatroom></chatroom>');
16     var chatroom = compile(ele)(scope);
17     scope.$digest();
18     expect(chatroom.html()).toContain('发送');
19   });
20 });
chatroomDirectiveSpec

但是如果我在模板中绑定了ng-controller,则会报错。有人知道怎么将controller绑定到模板上吗?如果有知道的,求在http://www.cnblogs.com/towersxu/p/4600298.html 上面留言。下面是为尝试将controller绑定到模板上的方法:

/**
 * Created by taox on 15-6-30.
 */
describe('Unit:Directives',function(){
  var scope,compile,chatroomCtrl;

  beforeEach(module('chatroomDirective'));
  beforeEach(module('directives/chatroom/chatroom.html'));
  beforeEach(inject(function($compile,$controller,$rootScope){
    compile = $compile;
    scope = $rootScope.$new();
    chatroomCtrl = $controller('chatroomCtrl',{$scope:scope,$routeParams:{roomId:'1'}});
  }));

  it('should display words 发送',function(){
    var ele = angular.element('<chatroom></chatroom>');
    var chatroom = compile(ele)(scope);
    scope.$digest();
    expect(chatroom.html()).toContain('发送');
  });
});

  错误提示为:Unknown provider:$routeParamsProvider<- $routeParams <-chatroomCtrl.我在测试controller的时候就不会出现这个错误。

posted @ 2015-07-03 17:02  hippor  阅读(936)  评论(1编辑  收藏  举报