关于Angular 1 测试问题

SCRUM 敏捷开发方法支持
Problem Domain
Technical Stack
https://github.com/angular-app/angular-app
Regarding files organization strategy,a build system,and basic workflows employed.

关于编译系统:
AngularJS需要处理目录层级和模块层级关系。
允许多个AngularJS 模块放到一个文件中
AngularJS模块也可以分布在多个文件中。
最好每个js文件只定义一个模块。

当我们声明好一个module时,我们就会拿它来注册对象创建配方,这些配方被称为providers。
每个provider在执行时都回产生一个运行时service实例。
这种Provider可能有多种特例比如factory,service,varaible,constant等)

var adminProjects = angular.module('admin-projects', []);
adminProjects.controller('ProjectsListCtrl', function($scope) {
//controller's code go here
});
adminProjects.controller('ProjectsEditCtrl', function($scope) {
//controller's code go here
});

每个module都可以有多个配置和run块。
AngularJS支持两种配置阶段的注册函数,我们可以为angular.module() 配置第三个参数

angular.module('admin-projects',[],function(){
    //configuration logic goes here
});
该形式的替代方法是config(),可以调用多次。
angular.module('admin-projects', [])
    .config(function() {
        //configuration block 1
    })
    .config(function() {
        //configuration block 2
    });
如此我们可以把较大的配置块,分拆成多个小块,突出功能主题。

Jasmine test
behavior-driven development framework for testing JavaScript code.

describe('hello world test',function(){
    var greeter;
    beforeEach(function(){
        greeter = new Greeter();
    });
    it('Should say hello to the world',function(){
        expect(greeter.say('world')).toEqual('Hello, World!');
    });
});

真正的测试用例隐藏在it体内,而beforeEach则是指定在运行每一个it体之前需要执行的内容。
expect 和 toEqual,toBeTruthy, toBeDefined, toContain 判断。

所有的测试相关的外部扩展和模拟对象都包含在angular-mocks.js文件里。

对于Angular Service的测试,需要一些初始化工作。
Angular提供了一系列的方法将Jasmine 和依赖注入很好的融合。

angular.module('archive', [])
    .factory('notificationsArchive', function () {
        var archivedNotifications = [];
        return {
            archive:function (notification) {
                archivedNotifications.push(notification);
            },
            getArchived:function () {
                return archivedNotifications;
            }
        };
});

测试代码:
describe('notifications archive tests', function () {
    var notificationsArchive;
    beforeEach(module('archive'));
    beforeEach(inject(function (_notificationsArchive_) {
        notificationsArchive = _notificationsArchive_;
    }));

    it('should give access to the archived items', function () {
        var notification = {msg: 'Old message.'};
        notificationsArchive.archive(notification);
        expect(notificationsArchive.getArchived()).toContain(notification);
    });
});

这里使用了module和inject函数来初始化加载需要的内容。
module函数时Jasmine中加载某个模块,它类似于 ng-app 指令。告诉AngularJS $injector 应该创建某个模块。
加载模块后,我们就可以通过inject来注入任意的模块定义内容了。


Controller测试:
angular.module('admin-projects', [])
    .controller('ProjectsEditCtrl', function($scope, project) {
        $scope.project = project;
        $scope.removeTeamMember = function(teamMember) {
            var idx = $scope.project.teamMembers.indexOf(teamMember);
            if(idx >= 0) {
                $scope.project.teamMembers.splice(idx, 1);
            }
    };
    //other methods of the controller
    });
    
    
测试代码:
describe('ProjectsEditCtrl tests', function () {
    var $scope;
    beforeEach(module('admin-projects'));
    beforeEach(inject(function ($rootScope) {
        $scope = $rootScope.$new();
    }));
    
    it('should remove an existing team member', inject(function($controller) {
        var teamMember = {};
        $controller('ProjectsEditCtrl', {
            $scope: $scope,
            project: {
                teamMembers: [teamMember]
            }
        });
        //verify the initial setup
        expect($scope.project.teamMembers).toEqual([teamMember]);
        //execute and verify results
        $scope.removeTeamMember(teamMember);
            expect($scope.project.teamMembers).toEqual([]);
    }));
});

要测试定义在Controller上的方法,我们需要先定义一个新的scope对象,一个controller实例,并把这两者链接起来。
我们还有手动的完成类似ng-controller指令的工作。

我们首先访问$rootScope服务调用其$new来创建一个新的$scope实例($scope.$new())
这是在模拟应用程序开始运行时的工作,此时ng-controller会创建一个新的scope

我们接着调用$controller服务创建一个controller实例,将前面创建的$scope 传递给它。

模拟对象和异步代码测试:
angular.module('async', [])
    .factory('asyncGreeter', function ($timeout, $log) {
        return {
            say:function (name, timeout) {
                $timeout(function(){
                    $log.info("Hello, " + name + "!");
                })
            }
        };
    });
    
$timeout服务是JavaScript的setTimeout函数的替代,延迟执行某些行为。

describe('Async Greeter test', function () {
    var asyncGreeter, $timeout, $log;
    
    beforeEach(module('async'));
    
    beforeEach(inject(function (_asyncGreeter_, _$timeout_, _$log_) {
        asyncGreeter = _asyncGreeter_;
        $timeout = _$timeout_;
        $log = _$log_;
    }));
    it('should greet the async World', function () {
        asyncGreeter.say('World', 9999999999999999999);
        //
        $timeout.flush();
        expect($log.info.logs).toContain(['Hello, World!']);
    });
});

通过调用$timeout.flush() ,来模拟一次异步事件的触发。


端到端测试,Scenario Runner
通过在真实浏览器内驱动行为来进行集成测试,它自动执行表单填写,单击按钮和链接等行为,检查页面回复,包括页面变化,信息显示等。

转载于:https://my.oschina.net/u/924064/blog/901411

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值