热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

关于Angular.Js的自动化测试

web前端|js教程angularjs自动化测试,angular自动化测试,自动化测试web前端-js教程这篇文章主要介绍了关于Angular.Js的自动化测试,有着一定的参考价值

web前端|js教程关于Angular.Js的自动化测试
angularjs自动化测试,angular自动化测试,自动化测试
web前端-js教程
这篇文章主要介绍了关于Angular.Js的自动化测试,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下
一个展示的网站源码,vscode软件没有图标,ubuntu 使用bin,tomcat没装好,安卓sqlite图片存储,爬虫提取百度搜索,php ci 手册,南安谷歌seo公司,求职招聘 网站源码,oa办公网页源码,可视化模板编辑器lzw
当Angular项目的规模到达一定的程度,就需要进行测试工作了。为什么要自动化测试?1,提高产出质量。2,减少重构时的痛。反正我最近重构多了,痛苦经历多了。3,便于新人接手。下面这篇文章就给大家详细介绍了Angular.Js的自动化测试,有需要的朋友们可以参考借鉴。
淘宝一键复制源码,ubuntu限制ip登录,tomcat下载哪个版本的,内容安全爬虫,php商城系统合并,seo面膜lzw
本文着重介绍关于ng的测试部分,主要包括以下三个方面:
java租房系统源码,ubuntu系统FTP下载,看tomcat是几位的,Reddit爬虫程序,小程序加php源码,seo服务商找行者SEOlzw
框架的选择(Karma+Jasmine)

测试的分类和选择(单元测试 + 端到端测试)

在ng中各个模块如何编写测试用例

下面各部分进行详细介绍。

测试的分类

在测试中,一般分为单元测试和端到端测试,单元测试是保证开发者验证代码某部分有效性的技术,端到端(E2E)是当你想确保一堆组件能按事先预想的方式运行起来的时候使用。

其中单元测试又分为两类: TDD(测试驱动开发)和BDD(行为驱动开发)。

下面着重介绍两种开发模式。

TDD(测试驱动开发 Test-driven development)是使用测试案例等来驱动你的软件开发。

如果我们想要更深入点了解TDD,我们可以将它分成五个不同的阶段:

首先,开发人员编写一些测试方法。

其次,开发人员使用这些测试,但是很明显的,测试都没有通过,原因是还没有编写这些功能的代码来实际执行。

接下来,开发人员实现测试中的代码。

如果开发人员写代码很优秀,那么在下一阶段会看到他的测试通过。

然后开发人员可以重构自己的代码,添加注释,使其变得整洁,开发人员知道,如果新添加的代码破坏了什么,那么测试会提醒他失败。

其中的流程图如下:

关于Angular.Js的自动化测试
TDD

TDD的好处:

能驱使系统最终的实现代码,都可以被测试代码所覆盖到,也即“每一行代码都可测”。

测试代码作为实现代码的正确导向,最终演变为正确系统的行为,能让整个开发过程更加高效。

BDD是(行为驱动开发 Behavior-Driven Development)指的是不应该针对代码的实现细节写测试,而是要针对行为写测试。BDD测试的是行为,即软件应该怎样运行。

和TDD比起来,BDD是需要我们先写行为规范(功能明细),在进行软件开发。功能明细和测试看起来非常相似,但是功能明细更加含蓄一些。BDD采用了更详细的方式使得它看起来就像是一句话。

BDD测试应该注重功能而不是实际的结果。你常常会听说BDD是帮助设计软件,而不是像TDD那样的测试软件。

最后总结:TDD的迭代反复验证是敏捷开发的保障,但没有明确如何根据设计产生测试,并保障测试用例的质量,而BDD倡导大家都用简洁的自然语言描述系统行为的理念,恰好弥补了测试用例(即系统行为)的准确性。

测试框架选择

利用karma和jasmine来进行ng模块的单元测试。

Karma:是一个基于Node.js的Javascript测试执行过程管理工具,这个测试工具的一个强大特性就是,它可以监控(Watch)文件的变化,然后自行执行,通过console.log显示测试结果。

jasmine是一个行为驱动开发(BDD)的测试框架,不依赖任何js框架以及dom,是一个非常干净以及友好API的测试库.

Karma

karma是一个单元测试的运行控制框架,提供以不同环境来运行单元测试,比如chrome,firfox,phantomjs等,测试框架支持jasmine,mocha,qunit,是一个以nodejs为环境的npm模块.

Karma从头开始构建,免去了设置测试的负担,集中精力在应用逻辑上。会产生一个浏览器实例,针对不同浏览器运行测试,同时可以对测试的运行进行一个实时反馈,提供一份debug报告。

测试还会依赖一些Karma插件,如测试覆盖率Karma-coverage工具、Karman-fixture工具及Karma-coffee处理工具。此外,前端社区里提供里比较丰富的插件,常见的测试需求都能涵盖到。

安装测试相关的npm模块建议使用—-save-dev参数,因为这是开发相关的,一般的运行karma的话只需要下面两个npm命令:

npm install karma --save-devnpm install karma-junit-reporter --save-dev

然后一个典型的运行框架通常都需要一个配置文件,在karma里可以是一个karma.conf.js,里面的代码是一个nodejs风格的,一个普通的例子如下:

module.exports = function(config){ config.set({ // 下面files里的基础目录 basePath : '../', // 测试环境需要加载的JS信息 files : [ 'app/bower_components/angular/angular.js', 'app/bower_components/angular-route/angular-route.js', 'app/bower_components/angular-mocks/angular-mocks.js', 'app/js/**/*.js', 'test/unit/**/*.js' ], // 是否自动监听上面文件的改变自动运行测试 autoWatch : true, // 应用的测试框架 frameworks: ['jasmine'], // 用什么环境测试代码,这里是chrome` browsers : ['Chrome'], // 用到的插件,比如chrome浏览器与jasmine插件 plugins : [ 'karma-chrome-launcher', 'karma-firefox-launcher', 'karma-jasmine', 'karma-junit-reporter' ], // 测试内容的输出以及导出用的模块名 reporters: ['progress', 'junit'], // 设置输出测试内容文件的信息 junitReporter : { outputFile: 'test_out/unit.xml', suite: 'unit' } });};

运行时输入:

karma start test/karma.conf.js

jasmine

jasmine是一个行为驱动开发的测试框架,不依赖任何js框架以及dom,是一个非常干净以及友好API的测试库.

以下以一个具体实例说明test.js:

describe("A spec (with setup and tear-down)", function() { var foo; beforeEach(function() { foo = 0; foo += 1; }); afterEach(function() { foo = 0; }); it("is just a function, so it can contain any code", function() { expect(foo).toEqual(1); }); it("can have more than one expectation", function() { expect(foo).toEqual(1); expect(true).toEqual(true); });});

首先任何一个测试用例以describe函数来定义,它有两参数,第一个用来描述测试大体的中心内容,第二个参数是一个函数,里面写一些真实的测试代码

it是用来定义单个具体测试任务,也有两个参数,第一个用来描述测试内容,第二个参数是一个函数,里面存放一些测试方法

expect主要用来计算一个变量或者一个表达式的值,然后用来跟期望的值比较或者做一些其它的事件

beforeEach与afterEach主要是用来在执行测试任务之前和之后做一些事情,上面的例子就是在执行之前改变变量的值,然后在执行完成之后重置变量的值

开始单元测试

下面分别以控制器,指令,过滤器和服务四个部分来编写相关的单元测试。项目地址为angular-seed(点我)项目,可以下载demo并运行其测试用例。

demo中是一个简单的todo应用,会包含一个文本输入框,其中可以编写一些笔记,按下按钮可以将新的笔记加入笔记列表中,其中使用notesfactory封装LocalStorage来储存笔记信息。

先介绍一下angular中测试相关的组件angular-mocks。

了解angular-mocks

在Angular中,模块都是通过依赖注入来加载和实例化的,因此官方提供了angular-mocks.js测试工具来提供模块的定义、加载,依赖注入等功能。

其中一些常用的方法(挂载在window命名空间下):

angular.mock.module: module用来加载已有的模块,以及配置inject方法注入的模块信息。具体使用如下:

beforeEach(module('myApp.filters'));beforeEach(module(function($provide) { $provide.value('version', 'TEST_VER');}));

该方法一般在beforeEach中使用,在执行测试用例之前可以获得模块的配置。

angular.mock.inject: inject用来注入配置好的ng模块,来供测试用例里进行调用。具体使用如下:

it('should provide a version', inject(function(mode, version) { expect(version).toEqual('v1.0.1'); expect(mode).toEqual('app'); }));

其实inject里面就是利用angular.inject方法创建的一个内置的依赖注入实例,然后里面的模块和普通的ng模块的依赖处理是一样的。

Controller部分

Angular模块是todoApp,控制器是TodoController,当按钮被点击时,TodoController的createNote()函数会被调用。下面是app.js的代码部分。

var todoApp = angular.module('todoApp',[]);todoApp.controller('TodoController',function($scope,notesFactory){ $scope.notes = notesFactory.get(); $scope.createNote = function(){ notesFactory.put($scope.note); $scope.note=''; $scope.notes = notesFactory.get(); }});todoApp.factory('notesFactory',function(){ return { put: function(note){ localStorage.setItem('todo' + (Object.keys(localStorage).length + 1), note); }, get: function(){ var notes = []; var keys = Object.keys(localStorage); for(var i = 0; i

在todoController中用了个叫做notesFactory的服务来存储和提取笔记。当createNote()被调用时,会使用这个服务将一条信息存入LocalStorage中,然后清空当前的note。因此,在编写测试模块是,应该保证控制器初始化,scope中有一定数量的笔记,在调用createNote()之后,笔记的数量应该加一。

具体的单元测试如下:

describe('TodoController Test', function() { beforeEach(module('todoApp')); // 将会在所有的it()之前运行 // 我们在这里不需要真正的factory。因此我们使用一个假的factory。 var mockService = { notes: ['note1', 'note2'], //仅仅初始化两个项目 get: function() { return this.notes; }, put: function(content) { this.notes.push(content); } }; // 现在是真正的东西,测试spec it('should return notes array with two elements initially and then add one', inject(function($rootScope, $controller) { //注入依赖项目 var scope = $rootScope.$new(); // 在创建控制器的时候,我们也要注入依赖项目 var ctrl = $controller('TodoController', {$scope: scope, notesFactory:mockService}); // 初始化的技术应该是2 expect(scope.notes.length).toBe(2); // 输入一个新项目 scope.note = 'test3'; // now run the function that adds a new note (the result of hitting the button in HTML) // 现在运行这个函数,它将会增加一个新的笔记项目 scope.createNote(); // 期待现在的笔记数目是3 expect(scope.notes.length).toBe(3); }) );});

在beforeEach中,每一个测试用例被执行之前,都需要加载模块module("todoApp")

由于不需要外部以来,因此我们本地建立一个假的mockService来代替factory,用来模拟noteFactory,其中包含相同的函数,get()put() 。这个假的factory从数组中加载数据代替localStorage的操作。

在it中,声明了依赖项目$rootScope$controller,都可以由Angular自动注入,其中$rootScope用来获得根作用域,$controller用作创建新的控制器。

$controller服务需要两个参数。第一个参数是将要创建的控制器的名称。第二个参数是一个代表控制器依赖项目的对象,
$rootScope.$new()方法将会返回一个新的作用域,它用来注入控制器。同时我们传入mockService作为假factory。
之后,初始化会根据notes数组的长度预测笔记的数量,同时在执行了createNote()函数之后,会改变数组的长度,因此可以写出两个测试用例。

Factory部分

factory部分的单元测试代码如下:

describe('notesFactory tests', function() { var factory; // 在所有it()函数之前运行 beforeEach(function() { // 载入模块 module('todoApp'); // 注入你的factory服务 inject(function(notesFactory) { factory = notesFactory; }); var store = { todo1: 'test1', todo2: 'test2', todo3: 'test3' }; spyOn(localStorage, 'getItem').andCallFake(function(key) { return store[key]; }); spyOn(localStorage, 'setItem').andCallFake(function(key, value) { return store[key] = value + ''; }); spyOn(localStorage, 'clear').andCallFake(function() { store = {}; }); spyOn(Object, 'keys').andCallFake(function(value) { var keys=[]; for(var key in store) { keys.push(key); } return keys; }); }); // 检查是否有我们想要的函数 it('should have a get function', function() { expect(angular.isFunction(factory.get)).toBe(true); expect(angular.isFunction(factory.put)).toBe(true); }); // 检查是否返回3条记录 it('should return three todo notes initially', function() { var result = factory.get(); expect(result.length).toBe(3); }); // 检查是否添加了一条新纪录 it('should return four todo notes after adding one more', function() { factory.put('Angular is awesome'); var result = factory.get(); expect(result.length).toBe(4); });});

在TodoController模块中,实际上的factory会调用localStorage来存储和提取笔记的项目,但由于我们单元测试中,不需要依赖外部服务去获取和存储数据,因此我们要对localStorage.getItem()localStorage.setItem()进行spy操作,也就是利用假函数来代替这两个部分。

spyOn(localStorage,'setItem')andCallFake()是用来用假函数进行监听的。第一个参数指定需要监听的对象,第二个参数指定需要监听的函数,然后andCallfake这个API可以编写自己的函数。因此,测试中完成了对localStorage和Object的改写,使函数可以返回我们自己数组中的值。

在测试用例中,首先检测新封装的factory函数是否包含了get()put()这两个方法,,然后进行factory.put()操作后断言笔记的数量。

Filter部分

我们添加一个过滤器。truncate的作用是如果传入字符串过长后截取前10位。源码如下:

todoApp.filter('truncate',function(){ return function(input,length){ return (input.length > length ? input.substring(0,length) : input); }});

所以在单元测试中,可以根据传入字符串的情况断言生成子串的长度。

describe('filter test',function(){ beforeEach(module('todoApp')); it('should truncate the input to 1o characters',inject(function(truncateFilter){ expect(truncateFilter('abcdefghijkl',10).length).toBe(10); }); );});

之前已经对断言进行讨论了,值得注意的一点是我们需要在调用过滤器的时候在名称后面加入Filter,然后正常调用即可。

Directive部分

源码中的指令部分:

todoApp.directive('customColor', function() { return { restrict: 'A', link: function(scope, elem, attrs) { elem.css({'background-color': attrs.customColor}); } };});

由于指令必须编译之后才能生成相关的模板,因此我们要引入$compile服务来完成实际的编译,然后再测试我们想要进行测试的元素。

angular.element()会创建一个jqLite元素,然后我们将其编译到一个新生成的自作用域中,就可以被测试了。具体测试用例如下:

describe('directive tests',function(){ beforeEach(module('todoApp')); it('should set background to rgb(128, 128, 128)', inject(function($compile,$rootScope) { scope = $rootScope.$new(); // 获得一个元素 elem = angular.element("sample"); // 创建一个新的自作用域 scope = $rootScope.$new(); // 最后编译HTML $compile(elem)(scope); // 希望元素的背景色和我们所想的一样 expect(elem.css("background-color")).toEqual('rgb(128, 128, 128)'); }) );});

开始端到端测试

在端到端测试中,我们需要从用户的角度出发,来进行黑盒测试,因此会涉及到一些DOM操作。将一对组件组合起来然后检查是否如预想的结果一样。
在这个demo中,我们模拟用户输入信息并按下按钮的过程,检测信息能否被添加到localStorage中。

在E2E测试中,需要引入angular-scenario这个文件,并且建立一个html作为运行report的展示,在html中包含带有e2e测试代码的执行js文件,在编写完测试之后,运行该html文件查看结果。具体的e2e代码如下:

describe('my app', function() { beforeEach(function() { browser().navigateTo('../../app/notes.html'); }); var oldCount = -1; it("entering note and performing click", function() { element('ul').query(function($el, done) { oldCount = $el.children().length; done(); }); input('note').enter('test data'); element('button').query(function($el, done) { $el.click(); done(); }); }); it('should add one more element now', function() { expect(repeater('ul li').count()).toBe(oldCount + 1); }); });

我们在端到端测试过程中,首先导航到我们的主html页面app/notes.html,可以通过browser.navigateTo()来完成,element.query()函数选择了ul元素并记录其中有多少个初始化的项目,存放在oldCount变量中。

然后通过input('note').enter()来键入一个新的笔记,然后模拟一下点击操作来检查是否增加了一个新的笔记(li元素)。然后通过断言可以将新旧的笔记数进行对比。


推荐阅读
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • PHP图片截取方法及应用实例
    本文介绍了使用PHP动态切割JPEG图片的方法,并提供了应用实例,包括截取视频图、提取文章内容中的图片地址、裁切图片等问题。详细介绍了相关的PHP函数和参数的使用,以及图片切割的具体步骤。同时,还提供了一些注意事项和优化建议。通过本文的学习,读者可以掌握PHP图片截取的技巧,实现自己的需求。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文介绍了使用postman进行接口测试的方法,以测试用户管理模块为例。首先需要下载并安装postman,然后创建基本的请求并填写用户名密码进行登录测试。接下来可以进行用户查询和新增的测试。在新增时,可以进行异常测试,包括用户名超长和输入特殊字符的情况。通过测试发现后台没有对参数长度和特殊字符进行检查和过滤。 ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • 本文介绍了腾讯最近开源的BERT推理模型TurboTransformers,该模型在推理速度上比PyTorch快1~4倍。TurboTransformers采用了分层设计的思想,通过简化问题和加速开发,实现了快速推理能力。同时,文章还探讨了PyTorch在中间层延迟和深度神经网络中存在的问题,并提出了合并计算的解决方案。 ... [详细]
  • 本文详细介绍了cisco路由器IOS损坏时的恢复方法,包括进入ROMMON模式、设置IP地址、子网掩码、默认网关以及使用TFTP服务器传输IOS文件的步骤。 ... [详细]
  • 如何实现JDK版本的切换功能,解决开发环境冲突问题
    本文介绍了在开发过程中遇到JDK版本冲突的情况,以及如何通过修改环境变量实现JDK版本的切换功能,解决开发环境冲突的问题。通过合理的切换环境,可以更好地进行项目开发。同时,提醒读者注意不仅限于1.7和1.8版本的转换,还要适应不同项目和个人开发习惯的需求。 ... [详细]
  • PHP组合工具以及开发所需的工具
    本文介绍了PHP开发中常用的组合工具和开发所需的工具。对于数据分析软件,包括Excel、hihidata、SPSS、SAS、MARLAB、Eview以及各种BI与报表工具等。同时还介绍了PHP开发所需的PHP MySQL Apache集成环境,包括推荐的AppServ等版本。 ... [详细]
author-avatar
A-Alon_586
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有