AngularJS 单元测试:Karma Jasmine 教程

Angular.JS 最出色的功能之一是 测试与验证 方面。Google 的开发人员在开发 AngularJS 时,始终将测试放在第一位,并确保整个 AngularJS 框架都是可测试的。

在 AngularJS 中,测试通常使用 Karma(框架)进行。Angular JS 测试可以在没有 Karma 的情况下进行,但 Karma 框架在测试 AngularJS 代码方面具有如此出色的功能,因此使用该框架是有意义的。

  • 在 AngularJS 中,我们可以执行 单元测试 分别为控制器和指令。
  • 我们还可以对 AngularJS 进行端到端测试,即从用户角度进行测试。

Karma框架介绍与安装

业力是 测试自动化工具 由 Google 的 Angular JS 团队创建。使用 Karma 的第一步是安装 Karma。Karma 通过 npm 安装(npm 是一种包管理器,用于在本地机器上轻松安装模块)。

安装 Karma

通过 npm 安装 Karma 分为两个步骤。

步骤1) 在命令行中执行下面一行

npm install karma karma-chrome-launcher karma-jasmine

其中,

  1. npm 是节点包管理器的命令行实用程序,用于在任何机器上安装自定义模块。
  2. install 参数指示 npm 命令行实用程序需要安装。
  3. 命令行中指定了 3 个与 karma 协同工作所需的库。
    • karma 是用于测试目的的核心库。
    • karma-chrome-launcher 是一个单独的库,可以使 karma 命令被 chrome 浏览器识别。
    • karma-jasmine – 这将安装 jasmine,它是 Karma 的依赖框架。

步骤2) 下一步是安装 karma 命令行实用程序。这是执行 karma 行命令所必需的。karma 行实用程序将用于初始化 karma 环境以进行测试。

要安装命令行实用程序,请在命令行中执行以下命令

npm install karma-cli

其中,

  • karma-cli 用于安装 karma 的命令行界面,用于在命令行界面中写入 karma 命令。
  • Karma 框架的配置

    下一步是配置 karma,可以通过以下命令完成

    "karma –init"

    执行完上述步骤后,karma 将创建一个 karma.conf.js 文件。该文件可能看起来像下面的代码片段

    files: [
      'Your application Name'/AngularJS/AngularJS.js',
      'Your application Name'/AngularJS-mocks/AngularJS-mocks.js',
      'lib/app.js',
      'tests/*.js'
    ]

    上述配置文件告诉 karma 运行时引擎以下内容

    1. “您的应用程序名称” – 这将被您的应用程序的名称替换。
    2. 您的应用程序名称 '/AngularJS/AngularJS.js' – 这告诉 karma,你的应用程序依赖于 AngularJS 中的核心模块
    3. '你的应用程序名称'/AngularJS-mocks/AngularJS-mocks.js' – 这告诉 karma 使用 Angular.JS-mocks.js 文件中的 AngularJS 单元测试功能。
    4. 所有主要应用程序或业务逻辑文件都存在于应用程序的 lib 文件夹中。
    5. 测试文件夹将包含所有单元测试。

    要检查 karma 是否正常运行,请创建一个名为 Sample.js 的文件,输入以下代码并将其放在测试目录中。

    describe('Sample test', function() {
      it('Condition is true', function() {
        expect('AngularJS').toBe('AngularJS');
      });
    });

    上述代码有以下几个方面

    1. describe 函数用于对测试进行描述。在我们的例子中,我们为测试提供了“示例测试”的描述。
    2. “it”函数用于为测试命名。在我们的例子中,我们将测试命名为“条件为真”。测试的名称需要有意义。
    3. 'expect' 和 'toBe' 关键字的组合表明测试结果的预期值和实际值。如果实际值和预期值相同,则测试将通过,否则将失败。

    在命令提示符下执行以下行时,它将执行上述测试文件

    KARMA start

    以下输出取自 IDE Webstorm 其中执行了上述步骤。

    Karma 框架的配置

    1. 输出结果在 Karma 浏览器中 Webstorm. 该窗口显示在 karma 框架中定义的所有测试的执行情况。
    2. 这里您可以看到执行的测试的描述是“示例测试”。
    3. 接下来,您可以看到名为“条件为真”的测试本身被执行。
    4. 请注意,所有测试旁边都有绿色的“Ok”图标,表示所有测试都已通过。

    测试 AngularJS 控制器

    karma 测试框架还具有端到端测试控制器的功能。这包括测试控制器中使用的 $scope 对象。

    让我们看一个例子来了解如何实现这一点。

    在我们的例子中,

    我们首先需要定义一个控制器。该控制器将执行以下步骤

    1. 创建一个 ID 变量并为其赋值 5。
    2. 将 ID 变量分配给 $scope 对象。

    我们的测试将测试该控制器的存在,并测试 $scope 对象的 ID 变量是否设置为 5。

    首先,我们需要确保满足以下先决条件

    通过 npm 安装 Angular.JS-mocks 库。可以在命令提示符中执行下面一行命令来完成

    npm install Angular JS-mocks

    接下来是修改 karma.conf.js 文件,以确保测试中包含正确的文件。下面的部分仅显示了需要修改的 karma.conf.js 文件部分

    files: ['lib/AngularJS.js','lib/AngularJS-mocks.js','lib/index.js','test/*.js']
    • “文件”参数基本上告诉 Karma 运行测试所需的所有文件。
    • 运行 AngularJS 单元测试需要 AngularJS.js 和 AngularJS-mocks.js 文件
    • index.js 文件将包含控制器的代码
    • 测试文件夹将包含我们所有的 AngularJS 测试

    下面是我们的 Angular.JS 代码,它将作为文件 Index.js 存储在我们应用程序的测试文件夹中。

    下面的代码只做了以下事情

    1. 创建 AngularJS 模块 名为sampleApp
    2. 创建一个名为 AngularJSController 的控制器
    3. 创建一个名为 ID 的变量,赋予其值 5,并将其分配给 $scope 对象
    var sampleApp = AngularJS.module('sampleApp',[]);
    sampleApp.controller('AngularJSController', function($scope) {
        $scope.ID =5;
    });

    一旦上述代码成功执行,下一步就是创建一个 测试用例 以确保代码已正确编写和执行。

    我们的测试代码如下所示。

    代码将放在一个名为 ControllerTest.js 的单独文件中,该文件将放在测试文件夹中。以下代码仅执行以下关键操作

    1. beforeEach 函数 – 此函数用于在测试运行之前加载名为“sampleApp”的 AngularJS.JS 模块。请注意,这是 index.js 文件中模块的名称。
    2. $controller 对象是作为控制器“Angular JSController”的模拟对象创建的,该控制器在我们的 index.js 文件中定义。在任何类型的单元测试中,模拟对象代表将实际用于测试的虚拟对象。这个模拟对象实际上将模拟我们的控制器的行为。
    3. beforeEach(inject(function(_$controller_) – 这用于在我们的测试中注入模拟对象,以便它表现得像实际的控制器。
    4. var $scope = {}; 这是为 $scope 对象创建的模拟对象。
    5. var controller = $controller('AngularJSController', { $scope: $scope }); – 在这里我们检查是否存在名为“Angular.JSController”的控制器。在这里,我们还将 Index.js 文件中控制器中的 $scope 对象中的所有变量分配给测试文件中的 $scope 对象
    6. 最后,我们将 $scope.ID 与 5 进行比较
    describe('AngularJSController', function() {
        beforeEach(module('sampleApp'));
    
        var $controller;
    
        beforeEach(inject(function(_$controller_){
                  $controller = _$controller_;
        }));
    
        describe('$scope.ID', function() {
            it('Check the scope object', function() {
                var $scope = {};
                var controller = $controller('AngularJSController', { $scope: $scope });
                expect($scope.ID).toEqual(5);
            });
        });
    });

    上述测试将在 karma 浏览器中运行,并给出与上一主题中显示的相同的通过结果。

    测试 AngularJS 指令

    karma 测试框架还具有测试自定义指令的功能。这包括在自定义指令中使用的 templateURL。

    让我们看一个例子来了解如何实现这一点。

    在我们的示例中,我们将首先定义一个自定义指令,该指令执行以下操作

    1. 创建一个名为 sampleApp 的 AngularJS 模块
    2. 创建一个名为“Guru99”的自定义指令
    3. 创建一个函数,返回一个带有标题标签的模板,该标签显示文本“这是 AngularJS 测试”。
    var sampleApp = AngularJS.module('sampleApp',[]);
    sampleApp.directive('Guru99', function () {
        return {
            restrict: 'E',
            replace: true,
            template: '<h1>This is AngularJS Testing</h1>'
        };
    });

    一旦上述代码成功执行,下一步就是创建一个测试用例,以确保代码已正确编写和执行。我们的测试代码如下所示

    代码将位于名为 DirectiveTest.js 的单独文件中,该文件将放置在测试文件夹中。以下代码仅执行以下关键操作

    1. beforeEach 函数——此函数用于在测试运行之前加载名为“sampleApp”的 Angular JS 模块。
    2. $compile 服务用于编译指令。此服务是必需的,需要声明,以便 Angular.JS 可以使用它来编译我们的自定义指令。
    3. $rootscope 是任何 AngularJS.JS 应用程序的主要范围。我们在前面的章节中已经看到了控制器的 $scope 对象。好吧,$scope 对象是 $rootscope 对象的子对象。在这里声明它的原因是我们通过自定义指令对 DOM 中的实际 HTML 标签进行更改。因此,我们需要使用 $rootscope 服务,该服务实际上会监听或知道 HTML 文档中发生的任何更改。
    4. var 元素 = $compile(“ ”)——这用于检查我们的指令是否按应有的方式注入。我们的自定义指令的名称是 Guru99,我们从自定义指令章节中知道,当指令注入到我们的 HTML 中时,它将被注入为 ' '。因此,该语句用于进行该检查。
    5. expect(element.html()).toContain(“This is AngularJS Testing”) – 这用于指示 expect 函数应该找到元素(在我们的例子中是 div 标签)以包含“This is AngularJS Testing”的 innerHTML 文本。
    describe('Unit testing directives', function() {
      var $compile,
          $rootScope;
       beforeEach(module('sampleApp'));
    
      beforeEach(inject(function(_$compile_, _$rootScope_){
        $compile = _$compile_;
        $rootScope = _$rootScope_;
     }));
    
     it('Check the directive', function() {
        // Compile a piece of HTML containing the directive
        var element = $compile("<ng-Guru99></ng-Guru99>")($rootScope);
        $rootScope.$digest();
        expect(element.html()).toContain("This is AngularJS Testing");
      });
    });

    上述测试将在 karma 浏览器中运行,并给出与上一主题中显示的相同的通过结果。

    端到端测试 AngularJS JS 应用程序

    karma 测试框架以及名为 Protractor 的框架具有端到端测试 Web 应用程序的功能。

    因此,它不仅是指令和控制器的测试,也是对 HTML 页面上可能出现的任何其他内容的测试。

    让我们看一个例子来了解如何实现这一点。

    在下面的示例中,我们将有一个使用 ng-repeat 指令创建数据表的 AngularJS 应用程序。

    1. 我们首先创建一个名为“tutorial”的变量,并一次性为其分配一些键值对。显示表格时,每个键值对都将用作数据。然后将 tutorial 变量分配给范围对象,以便可以从我们的视图中访问它。
    2. 对于表中的每一行数据,我们都使用 ng-repeat 指令。该指令使用变量 ptutor 遍历教程范围对象中的每个键值对。
    3. 最后,我们使用标签以及键值对(ptutor.Name 和 ptutor.Description)来显示表格数据。
    <table >
                 <tr ng-repeat="ptutor in tutorial">
                       <td>{{ ptutor.Name }}</td>
    	               <td>{{ ptutor.Description }}</td>
                 </tr>
       </table>
    </div>
      <script type="text/javascript">
          var app = AngularJS.module('DemoApp', []);
            app.controller('DemoController', function($scope) {
               $scope.tutorial =[
                    {Name: "Controllers" , Description : "Controllers in action"},
                    {Name: "Models" , Description : "Models and binding data"},
    	            {Name: "Directives" , Description : "Flexibility of Directives"}
    			]   });

    一旦上述代码成功执行,下一步就是创建一个测试用例,以确保代码已正确编写和执行。我们的测试代码如下所示

    我们的测试实际上要测试 ng-repeat 指令并确保它包含如上例所示的 3 行数据。

    首先,我们需要确保满足以下先决条件

    通过 npm 安装量角器库。这可以通过在命令提示符中执行下面一行来完成

    "npm install protractor"

    我们的测试代码如下所示。

    代码将放在一个名为 CompleteTest.js 的单独文件中,该文件将放在测试文件夹中。下面的代码只执行以下关键操作

    1. 浏览器功能由量角器库提供,并假定我们的 AngularJS 应用程序(使用上面显示的代码)正在我们的网站 URL 上运行 - http://localhost:8080/Guru99/
    2. var list=element.all(by.repeater(ptutor in tutorial')); - 这行代码实际上是在获取由代码“ptutor in tutorial”填充的 ng-repeat 指令。element 和 by.repeater 是 protractor 库提供的特殊关键字,可让我们获取 ng-repeat 指令的详细信息。
    3. expect(list.count()).toEqual(3); – 最后,我们使用 expect 函数来查看我们确实由于 ng-repeat 指令而获得了表中填充的 3 个项目。
    Describe('Unit testing end to end', function() {
      beforeEach(function() {
    browser.get('http://localhost:8080/Guru99/');
    })
       it('Check the ng directive', function() {
          var list=element.all(by.repeater(ptutor in tutorial'));
          expect(list.count()).toEqual(3);  }); });

    上述测试将在 karma 浏览器中运行,并给出与上一主题中显示的相同的通过结果。

    结语

    • AngularJS 中的测试是通过使用 Google 自己开发的框架 karma 框架实现的。
    • karma 框架使用 node 包管理器安装。基本测试需要安装的关键模块是 karma、karma-chrome-launcher、karma-jasmine 和 karma-cli。
    • 测试写在单独的 js 文件中,通常保存在应用程序的测试文件夹中。这些测试文件的位置必须在名为 karma.conf.js 的特殊配置文件中提及。Karma 在执行所有测试时使用此配置文件。
    • Karma 也可以用来测试控制器和自定义指令。
    • 对于端到端 Web 测试,需要通过 Node 包管理器安装另一个名为 protractor 的框架。该框架提供了一些特殊方法,可用于测试 HTML 页面上的所有元素。