手机版

角度自动测试详解 射流研究…

时间:2021-09-07 来源:互联网 编辑:宝哥软件园 浏览:

本文重点研究ng的测试部分,主要包括以下三个方面:

框架的选择(Karma Jasmine)测试的分类和选择(单元测试的端到端测试)如何为ng中的每个模块编写测试用例将在下面的章节中详细描述。

测试分类

在测试中,一般分为单元测试和端到端测试。单元测试是一种确保开发人员验证代码的某个部分的有效性的技术,当您想要确保一堆组件能够以预先预期的方式运行时,会使用端到端(E2E)测试。

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

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

测试驱动开发是用测试用例来驱动你的软件开发。

如果我们想更多地了解TDD,我们可以将其分为五个不同的阶段:

首先,开发人员编写一些测试方法。其次,开发人员使用了这些测试,但是很明显,它们都没有通过,因为这些函数的代码还没有被编写来实际执行它们。接下来,开发人员实现测试中的代码。如果开发人员写了好的代码,他将在下一阶段通过测试。然后开发人员可以重构自己的代码,添加注释并使其整洁。开发人员知道,如果新添加的代码破坏了什么,测试会提醒他失败。流程图如下:

TimeDivisionDuplex 时分双工

TDD的优点:

任何能够驱动系统最终实现的代码都可以被测试代码覆盖,即“每一行代码都可以被测试”。测试代码作为实现代码的正确导向,最终演化为正确的系统行为,可以使整个开发过程更加高效。BDD是(行为驱动开发),这意味着测试不应该为代码的实现细节而编写,而应该为行为而编写。BDD测试行为,也就是软件应该如何运行。

与TDD相比,BDD要求我们编写行为规范(功能细节)和开发软件。功能细节和测试看起来非常相似,但是功能细节更加微妙。BDD采用了更详细的方法,使其看起来像一个句子。BDD测试应该关注功能而不是实际结果。你经常听到BDD是帮助设计软件,而不是像TDD那样测试软件。最后得出结论,TDD的迭代验证是敏捷开发的保障,但如何根据设计生成测试,保证测试用例的质量,目前还不清楚。BDD提倡大家用简洁的自然语言来描述系统行为的思想,这正好弥补了测试用例(即系统行为)的准确性。

测试框架选择

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

Karma:是一个基于Node.js的JavaScript测试执行过程管理工具,这个测试工具的一个强大功能就是可以观察文件的变化,然后自己执行,通过console.log显示测试结果

Jasmine是一个行为驱动开发(BDD)的测试框架,它不依赖于任何js框架和dom,是一个非常干净友好的API测试库。

因果报应

Karma是一个针对单元测试的操作控制框架,提供不同的环境来运行单元测试,比如Chrome、Firefox、Phantom JS等。测试框架支持jasmine、mocha、qunit Qunit,是一个基于nodejs的npm模块。

Karma是从头开始构建的,它消除了设置测试的负担,专注于应用程序逻辑。将生成一个浏览器实例,并将为不同的浏览器运行测试。同时,可以对测试的运行给出实时反馈,并提供调试报告。

测试也依赖于一些Karma插件,比如测试覆盖率Karma-coverage工具、Karman-fixture工具和Karma-coffee处理工具。此外,前端社区中有丰富的插件,可以覆盖常见的测试需求。

建议对与安装测试相关的npm模块使用-save-dev参数,因为它与开发相关。一般来说,运行karma只需要以下两个npm命令:

NPM安装因果报应-拯救-发展NPM安装因果报应-新闻-记者-拯救-发展。那么一个典型的运行框架通常需要一个配置文件,可以是karma中的karma.conf.js,里面的代码是nodejs风格的。常见的例子如下:

module . exports=function(config){ config . set({//基本目录basePath : './'在下面的文件中,//JS信息文件:[' 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 ','测试/单元/* */*。js'],//是否自动监控上述文件的变化并自动运行测试autoWatch : true。//应用测试框架framework :[' jasmine '],//用什么环境测试代码,这里是Chrome 'Browsers : ['chrome']使用的插件,//。Chrome浏览器和jasmine插件插件: ['karma-chrome-launcher ',' karma-Firefox-launcher ',' karma-jasmine ',' karma-JUnit-reporter'],//模块名reporter 3360[' progress ',' JUnit']用于输出和导出测试内容,//设置输出测试内容文件JUnit reporter3360的信息{ output file 3360 ' test _ out/unit . XML ',suite : ' unit ' });};运行时输入:

karma start test/karma . conf . jsjasmine

Jasmine是一个行为驱动开发的测试框架,它不依赖于任何js框架和dom。这是一个非常干净且对应用编程接口友好的测试库。

下面用一个具体的例子来说明test.js:

描述('一个规格(带有设置和拆卸)',函数(){ var foobefore EACH(function(){ foo=0;foo=1;});after EACH(function(){ foo=0;});它('只是一个函数,所以可以包含任何代码',function() { expect(foo))。toeqal(1);});it('可以有多个期望',function() { expect(foo))。toeqal(1);期待(真实)。toEqual(真);});});首先,任何一个测试用例都是用description function来定义的,它有两个参数,第一个是用来描述测试的一般中心内容,第二个是函数,其中一些真实的测试代码它是为了定义单个特定的测试任务而编写的,还有两个参数,第一个是用来描述测试内容的,第二个是函数,还有一些测试方法,expect, 主要用于计算变量或表达式的值,然后将其与期望值进行比较或做一些其他事件。 beforeEach和afterEach主要用于在执行测试任务之前和之后做一些事情。上面的例子是在执行之前改变变量的值,然后在执行之后重置变量的值来开始单元测试

相关的单元测试分为四个部分:控制器、指令、过滤器和服务。项目地址是angular-seed项目,您可以下载demo并运行它的测试用例。

Demo是一个简单的todo应用程序,里面有一个文本输入框,可以在里面写一些笔记,按下按钮可以在笔记列表中添加新的笔记,其中notesfactory用于封装LocalStorage来存储笔记信息。

首先,我们将在angular中介绍与测试相关的组件角度模型。

理解角度模型

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

一些常用的方法(安装在窗口命名空间下):

angular.mock.module:模块用于加载现有模块并配置通过inject方法注入的模块信息。具体用途如下:

beforeEach(模块(' Myapp . filters '));beforeEach(模块(函数($ provide){ $ provide . value(' version ',' TEST _ VER ');}));这种方法一般用在beforeEach中,在执行测试用例之前可以得到模块的配置。

Angular.mock.inject: inject用于注入已配置的ng模块,以便在测试用例中调用。具体用途如下:

it('应该提供一个版本',inject(函数(模式,版本){ expect(版本))。toeqal(' v 1 . 0 . 1 ');期望(模式)。toeqal(' app ');}));实际上,inject是使用angular.inject方法创建的内置依赖注入实例,然后里面的模块的依赖处理和普通ng模块是一样的。

控制器部分

角度模块是todoApp,控制器是TodoController。单击按钮时,将调用TodoController的createNote()函数。下面是app.js的代码部分

var todo app=angular . module(' todo app ',[]);todoapp . controller(' TodoController ',function($scope,notes factory){ $ scope . notes=notes factory . get();$ scope . create note=function(){ notes factory . put($ scope . note);$ scope.note=$ scope . notes=notesfactory . get();}});todoApp.factory('notesFactory ',function(){ return { put : function(note){ local storage . setitem(' todo ')(object . keys(local storage))。长度1),注);},get : function(){ var notes=[];变量键=对象键(本地存储);for(var I=0;长度;I){ notes . push(local storage . getitem(keys[I]);}回执;} };});在todoController中,一种称为notesFactory的服务用于存储和检索笔记。当调用createNote()时,它将使用此服务在LocalStorage中存储消息,然后清除当前注释。所以写测试模块的时候,控制器要初始化,范围内有一定数量的笔记。调用createNote()后,音符的数量应该增加一个。

具体的单元测试如下:

描述(' TodoController Test ',function() { beforeEach(模块(' todo app ')));//它将先于所有it()运行。//我们这里不需要真正的工厂。因此,我们使用一个假工厂。varmockservice={ note s 3360[' note 1 ',' note2'],//只需初始化两个项目get3360function () {returnthis。笔记;},put:函数(内容){ this.notes.push(内容);} };//现在是真的了,测试spec it('最初应该返回带有两个元素的notes数组,然后添加一个',inject (function ($ rootscope,$ controller) {//inject依赖的项目var scope=$rootScope。$ new();//创建控制器时,我们还需要注入依赖项目varctrl=$ controller(' to doccontroller ',{ $ scope:scope,notesfactory : monkservice });//初始化技术应该是2expect (scope.notes.length)。托比(2);//输入新的项目范围。注意=' test3//现在运行添加新注释的函数(html中点击按钮的结果)//现在运行这个函数,它会添加一个新的注释项作用域. create note();//预计现在的笔记数量为3expect(范围。notes.length)。托比(3);}) );});在beforeEach中,在执行每个测试用例之前,需要加载模块(“todoApp”)。

由于不需要外部函数,我们在本地创建了一个假的mockService,而不是factory来模拟noteFactory,它包含相同的函数get()和put()。假工厂从阵列中加载数据,而不是本地存储操作。

其中声明了依赖项$rootScope和$controller可以由Angular自动注入,其中$rootScope用于获取根作用域,$controller用于创建新的控制器。

$controller服务需要两个参数。第一个参数是要创建的控制器的名称。第二个参数是表示控制器所依赖的项目的对象。$rootScope。$new()方法将返回一个新的作用域,用于注入控制器。同时,我们引入了mockService作为假工厂。之后,初始化根据notes数组的长度预测音符的个数,执行createNote()函数后,数组的长度会发生变化,所以可以写两个测试用例。

工厂部分

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

描述(' notesFactory tests ',function(){ var factory;//在所有它()函数之前运行beforeEach(function() { //载入模块模块(' ToDoapp ');//注入你的工厂服务inject(function(notes factory){ factory=notes factory;});var store={ todo1: 'test1 ',todo2: 'test2 ',todo 3: ' test3 ' };spyOn(localStorage,' getItem ').andcalFax(function(key){ return store[key];});spyOn(localStorage,' setItem ').andCallFake(函数(键,值){返回存储[键]=值"";});spyOn(localStorage,' clear ').andCallFake(function(){ store={ };});对象,"键")。andCallFake(function(value){ var key=[];for(存储中的var密钥){ keys。推(键);}回车键;});});//检查是否有我们想要的函数它('应该有一个得到函数,function(){ expect(angular。IsFunction(工厂。得到).toBe(真);期待(棱角分明。是功能(工厂。放入).toBe(真);});//检查是否返回3条记录它('最初应该返回三个todo notes ',function(){ var result=factory。get();期望(结果。长度)。托比(3);});//检查是否添加了一条新纪录它('多加一个后应该返回四个待办事项,function(){ factory。放('有角度很牛逼');var结果=工厂。get();期望(结果。长度)。托比(4);});});在到控制器模块中,实际上的工厂会调用localStorage来存储和提取笔记的项目,但由于我们单元测试中,不需要依赖外部服务去获取和存储数据,因此我们要对localStorage.getItem()和localStorage.setItem()进行间谍操作,也就是利用假函数来代替这两个部分。

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

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

过滤器部分

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

todoApp.filter('truncate ',function(){ return function(输入,长度){ return(输入。长度长度?input.substring(0,长度):输入);}});所以在单元测试中,可以根据传入字符串的情况断言生成子串的长度。

描述(“筛选测试”,函数(){ beforeEach(模块(' todoApp '));它('应该将输入截断为1o个字符,注入(函数(截短过滤器){ expect(截短过滤器(' abcdefghijkl ',10)).长度)。托比(10);}););});之前已经对断言进行讨论了,值得注意的一点是我们需要在调用过滤器的时候在名称后面加入过滤器,然后正常调用即可。

管理的部分

源码中的指令部分:

todoApp.directive('customColor ',function(){ return { restrict : ' A ',link: function(scope,elem,attrs){ elem。CSS({ '底色' : attrs。自定义颜色});} };});由于指令必须编译之后才能生成相关的模板,因此我们要引入$编译服务来完成实际的编译,然后再测试我们想要进行测试的元素。

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

description(' directive tests ',function(){ beforeach(module(' todoApp '))));它('应该将背景设置为rgb(128,128,128)',inject(function($compile,$rootScope) { scope=$rootScope .$ new();//获得一个元素elem=角度。元素(' span custom-color=\ ' RGB(128,128,128)\ ' sample/span ');//创建一个新的自作用域作用域=$rootScope .$ new();//最后编译HTML $编译(elem)(范围);//希望元素的背景色和我们所想的一样expect(elem.css('背景色')。toeqal(' RGB(128,128,128)');}) );});开始端到端测试

在端到端测试中,我们需要从用户的角度进行黑盒测试,所以会涉及到一些DOM操作。组合一对组件,检查结果是否如预期。在这个演示中,我们模拟了用户输入信息并按下按钮来检查信息是否可以添加到本地存储的过程。

在E2E测试中,有必要引入文件angular-scenario,并创建一个html作为运行报告的表示,其中包含带有e2e测试代码的执行js文件。编写测试后,运行html文件查看结果。具体的e2e代码如下:

描述('我的应用程序',函数(){ beforeEach(函数(){ browser()。导航到('././app/notes . html’);});var old count=-1;it('输入音符并执行click ',function() { element('ul ')。查询(函数($el,done) { oldCount=$el.children()。长度;done();});输入('注释')。输入('测试数据');元素('按钮')。query(function($el,done){ $ El . click();done();});});it('现在应该再添加一个元素',function(){ expect(repeater)(' ul Li ')。count())。toBe(旧计数1);});});在端到端的测试过程中,我们首先导航到我们的主html页面app/notes.html,这可以通过browser.navigateTo()来完成。element.query()函数选择ul元素,并记录oldCount变量中存储了多少初始化的项目。

然后通过输入输入新的音符(“音符”)。输入(),然后模拟单击操作,检查是否添加了新注释(li元素)。然后你可以通过断言来比较新旧音符的数量。

摘要

以上就是本文的全部内容。希望这篇文章的内容对你的学习或工作有所帮助。有问题可以留言交流。

版权声明:角度自动测试详解 射流研究…是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。