Тестване на модули на AngularJS с Karma и Jasmine

⚡ Умно обобщение

Тестването на модули на AngularJS с Karma и Jasmine проверява контролери, директиви и услуги изолирано. Karma изпълнява спецификации в реални браузъри, Jasmine предоставя синтаксиса на твърденията, а angular-mocks инжектира зависимости без реален сървър.

  • 🧱 Разделяне на инструментите: Karma е инструментът за изпълнение на тестове, Jasmine е рамката за спецификации, а angular-mocks предоставя помощни инструменти за инжектиране на зависимости.
  • Път на инсталиране: Инсталирайте karma, karma-chrome-launcher, karma-jasmine и karma-cli чрез npm, след което генерирайте karma.conf.js.
  • 📁 Правило за конфигурация: Масивът от файлове трябва да изброява angular.js, angular-mocks.js, изходните кодове на приложението и папката test в този ред.
  • 🎛️ Тестване на контролера: Инжектирайте услугата $controller, предайте фалшив обект $scope и след това потвърдете стойностите, които контролерът присвоява.
  • 🧩 Тестване на директиви: Използвайте $compile с $rootScope, извикайте $digest и проверете рендираната маркировка, върната от директивата.
  • 🌐 Слой от край до край: професионалистtractor управлява работещо приложение и брои повтарящи се редове, генерирани от ng-repeat.
  • 📌 Състояние на поддръжката: AngularJS достигна края на жизнения си цикъл на 31 декември 2021 г., така че третирайте този работен процес като наследствено знание за поддръжка.

Тестване на модули в AngularJS с Karma и Jasmine

Една от най-брилянтните характеристики на AngularJS е Тестване аспект. Когато разработчиците в Google Разработвайки AngularJS, те са имали предвид тестването и са се уверили, че цялата AngularJS рамка е тестваема.

В AngularJS тестването обикновено се извършва с помощта на Karma (фреймуърк). Тестването с AngularJS може да се извърши и без Karma, но Karma framework има толкова брилянтна функционалност за тестване на AngularJS код, че е логично да се използва този фреймуърк.

⚠️ Бележка към версията: AngularJS (версия 1.x) достигна официалния край на жизнения си цикъл на 31 декември 2021 г., а Pro...tractor беше оттеглен през август 2023 г. Работният процес на тази страница остава валиден за поддръжка на съществуващи AngularJS 1.x приложения. Новите проекти трябва да използват модерен Angular с поддържан в момента runner.

Въведение и инсталиране на рамката Karma

Кармата е а инструмент за автоматизация на тестването създадено от екипа на AngularJS в GoogleПървата стъпка за използване на Karma е инсталирането на Karma. Karma се инсталира чрез npm (който е мениджър на пакети, използван за лесно инсталиране на модули на локална машина).

Инсталиране на Карма

Инсталирането на Karma чрез npm се извършва в процес от две стъпки.

Стъпка 1) Изпълнете реда по-долу от командния ред

npm install karma karma-chrome-launcher karma-jasmine --save-dev

при което,

  1. npm е помощната програма за командния ред за мениджъра на пакети на node, използвана за инсталиране на персонализирани модули на всяка машина. Тя се доставя с Node.js.
  2. Инсталационният параметър указва на помощната програма от командния ред npm, че е необходима инсталация.
  3. Има 3 библиотеки, посочени в командния ред, които са необходими за работа с karma.
    • karma е основната библиотека, която ще се използва за целите на тестването.
    • karma-chrome-launcher е отделна библиотека, която позволява командите на karma да бъдат разпознавани от браузъра chrome.
    • karma-jasmine – Това инсталира jasmine, който е зависима рамка за Karma.

Стъпка 2) Следващата стъпка е да инсталирате помощната програма за команден ред karma. Това е необходимо за изпълнение на команди от карма линия. Помощната програма karma line ще се използва за инициализиране на karma средата за тестване.

За да инсталирате помощната програма за командния ред, изпълнете реда по-долу от командния ред

npm install -g karma-cli
  • karma-cli се използва за инсталиране на командния интерфейс за karma, който ще се използва за писане на командите на karma в интерфейса на командния ред. Флагът -g го инсталира глобално, така че командата karma е достъпна от всяка папка.

Конфигуриране на рамката Karma

Следващата стъпка е да конфигурирате karma, което може да се направи чрез командата

karma init

След като горната стъпка бъде изпълнена, karma ще създаде файл karma.conf.js. Файлът вероятно ще изглежда като фрагмента, показан по-долу

files: [
  'node_modules/angular/angular.js',
  'node_modules/angular-mocks/angular-mocks.js',
  'lib/app.js',
  'tests/*.js'
]

Горните конфигурационни файлове казват на системата за изпълнение на karma следните неща

  1. angular.js – Това казва на кармата, че приложението ви зависи от основните модули в AngularJS.
  2. angular-mocks.js – Това казва на карма да използва функционалността за модулно тестване за AngularJS от файла angular-mocks.js.
  3. Всички основни файлове на приложението или бизнес логиката присъстват в папката lib на вашето приложение.
  4. Папката с тестове ще съдържа всички тестове на модула.

💡 Съвет: Редът е важен в масива с файлове. angular.js трябва да се зареди преди angular-mocks.js и двата трябва да се заредят преди кода на приложението ви, в противен случай инжекторът няма да е наличен, когато спецификациите се изпълнят.

За да проверите дали 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 Framework

  1. Резултатът идва в карма изследователя вътре Webstorm. Този прозорец показва изпълнението на всички тестове, които са дефинирани в рамката на кармата.
  2. Тук можете да видите, че е показано описанието на изпълнения тест, което е „Примерен тест“.
  3. След това можете да видите, че самият тест, който има име „Условието е вярно“, се изпълнява.
  4. Имайте предвид, че тъй като всички тестове имат зелена икона „Ok“ до себе си, което символизира, че всички тестове са преминали успешно.

Какво е Jasmine в AngularJS Unit Testing?

Karma решава къде се изпълняват тестовете, докато Jasmine решава как се пишат. Jasmine е рамка за спецификации, базирана на поведение, която предоставя речника, използван във всеки пример на тази страница, поради което адаптерът karma-jasmine е инсталиран заедно с runner-а.

Жасмин допринася с четири градивни елемента:

  • описи(): Групира свързани спецификации в пакет и приема четливо описание на тестваното устройство.
  • то(): Декларира една спецификация. Името трябва да посочва поведението, което се проверява, а не метода, който се извиква.
  • очаквайте() със съпоставители: Сравнява действителна стойност с очаквана. Често срещани съпоставяния включват toBe, toEqual, toContain и toBeDefined.
  • предиВсеки() и следВсеки(): Изпълнявайте настройка и демонтаж преди и след всяка спецификация, което прави всеки тест независим.

Jasmine предоставя и шпиони. Шпионинът замества реална функция със записан заместител, така че контролерът може да бъде тестван без извикване на HTTP крайна точка. Тъй като Jasmine не се нуждае от DOM и собствена библиотека за твърдения, комбинацията от Karma и Jasmine остава най-лесният начин за изпълнение на AngularJS. JavaТестове на модули за скриптове.

Тестване на AngularJS контролери

Рамката за тестване на карма също има функционалността да тества контролерите от край до край. Това включва тестване на обекта $scope, който се използва в контролерите.

Нека да разгледаме пример как можем да постигнем това.

В нашия пример,

Първо ще трябва да дефинираме контролер. Този контролер ще извърши описаните по-долу стъпки

  1. Създайте ID променлива и й присвоете стойност 5.
  2. Присвоете променливата ID към обекта $scope.

Нашият тест ще тества съществуването на този контролер и ще тества дали променливата ID на обекта $scope е зададена на 5.

Първо трябва да се уверим, че е налице следното предварително условие

Инсталирайте библиотеката angular-mocks чрез npm. Това може да стане чрез изпълнение на следния ред в командния ред

npm install angular-mocks --save-dev

Следва да модифицирате файла karma.conf.js, за да сте сигурни, че са включени правилните файлове за теста. Сегментът по-долу показва просто файловата част от karma.conf.js, която трябва да бъде модифицирана

files: ['lib/angular.js', 'lib/angular-mocks.js', 'lib/index.js', 'test/*.js']
  • Параметърът „файлове“ основно казва на Karma всички файлове, които са необходими при изпълнението на тестовете.
  • Файловете angular.js и angular-mocks.js са необходими за изпълнение на модулни тестове на AngularJS.
  • Файлът index.js ще съдържа нашия код за контролера
  • Тестовата папка ще съдържа всички наши AngularJS тестове

По-долу е показан нашият AngularJS код, който ще бъде съхранен като файл Index.js в тестовата папка на нашето приложение.

Кодът по-долу прави само следните неща

  1. Създай AngularJS модул наречено sampleApp
  2. Създайте контролер, наречен AngularJSController
  3. Създайте променлива, наречена ID, дайте й стойност 5 и я присвойте на обекта $scope
var sampleApp = angular.module('sampleApp', []);
sampleApp.controller('AngularJSController', function($scope) {
  $scope.ID = 5;
});

След като горният код бъде изпълнен успешно, следващата стъпка ще бъде да се създаде a Тестов случай за да се гарантира, че кодът е написан и изпълнен правилно.

Кодът за нашия тест ще бъде както е показано по-долу.

Кодът ще бъде в отделен файл, наречен ControllerTest.js, който ще бъде поставен в тестовата папка. Кодът по-долу прави следните ключови неща

  1. Функция beforeEach – Тази функция се използва за зареждане на нашия AngularJS модул, наречен „sampleApp“, преди тестовото изпълнение. Обърнете внимание, че това е името на модула във файл index.js.
  2. Обектът $controller е създаден като макет на контролера „AngularJSController“, който е дефиниран в нашия index.js файл. Във всеки вид модулно тестване, макетният обект представлява фиктивен обект, който всъщност ще бъде използван за тестване. Този макетен обект всъщност ще симулира поведението на нашия контролер.
  3. beforeEach(inject(function(_$controller_) – Това се използва за инжектиране на макетния обект в нашия тест, така че да се държи като действителния контролер.
  4. var $scope = {}; Това е макет на обект, който се създава за обекта $scope.
  5. var controller = $controller('AngularJSController', { $scope: $scope }); – Тук проверяваме за съществуването на контролер с име 'AngularJSController'. Тук също така присвояваме всички променливи от нашия обект $scope в нашия контролер във файла Index.js на обекта $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 директиви

Рамката за тестване на карма има и функционалност за тестване на персонализирани директиви. Това включва шаблонаURLкоито се използват в рамките на персонализирани директиви.

Нека да разгледаме пример как можем да постигнем това.

В нашия пример първо ще дефинираме персонализирана директива, която прави следните неща

  1. Създайте модул AngularJS, наречен sampleApp
  2. Създайте персонализирана директива с име – guru99
  3. Създайте функция, която връща шаблон със заглавен таг, който показва текста „Това е тестване на AngularJS“.
var sampleApp = angular.module('sampleApp', []);
sampleApp.directive('guru99', function () {
  return {
    restrict: 'E',
    replace: true,
    template: '<h1>This is AngularJS Testing</h1>'
  };
});

След като горният код бъде изпълнен успешно, следващата стъпка ще бъде да се създаде тестов случай, за да се гарантира, че кодът е написан и изпълнен правилно. Кодът за нашия тест ще бъде както е показано по-долу

Кодът ще бъде в отделен файл, наречен DirectiveTest.js, който ще бъде поставен в тестовата папка. Кодът по-долу прави следните ключови неща

  1. Функция beforeEach – Тази функция се използва за зареждане на нашия AngularJS модул, наречен „sampleApp“, преди тестовото изпълнение.
  2. Услугата $compile се използва за компилиране на директивата. Тази услуга е задължителна и трябва да бъде декларирана, за да може AngularJS да я използва за компилиране на нашата персонализирана директива.
  3. $rootScope е основният обхват на всяко AngularJS приложение. Видяхме обекта $scope на контролера в по-ранни глави. Обектът $scope е дъщерен обект на обекта $rootScope. Причината това да е декларирано тук е, че правим промяна в действителен HTML таг в DOM чрез нашата персонализирана директива. Следователно, трябва да използваме услугата $rootScope, която всъщност слуша или знае кога се случва някаква промяна в рамките на HTML документ.
  4. var елемент = $compile(“ ”)($rootScope) – Това се използва за проверка дали нашата директива се инжектира както трябва. Директивата е регистрирана с името guru99, което е с малък регистър, така че AngularJS съвпада с елемента с малък регистър в маркировката. Следователно това твърдение се използва за извършване на тази проверка.
  5. очаквам(element.html()).toContain(“Това е AngularJS тестване”) – Това се използва, за да се инструктира функцията очакване, че трябва да намери елемента (в нашия случай тагът h1), който да съдържа вътрешния HTML текст на „Това е AngularJS тестване“.
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("<guru99></guru99>")($rootScope);
    $rootScope.$digest();
    expect(element.html()).toContain("This is AngularJS Testing");
  });
});

Горният тест ще се изпълнява в браузъра karma и ще даде същия резултат за преминаване, както беше показано в предишната тема.

Цялостно тестване на AngularJS приложения

Рамката за тестване на карма, заедно с рамка, наречена ProtracTor има функционалността да тества уеб приложение от край до край.

Така че това не е само тестване на директиви и контролери, но и тестване на всичко друго, което може да се появи на HTML страница.

Нека да разгледаме пример как можем да постигнем това.

В нашия пример по-долу ще имаме AngularJS приложение, което създава таблица с данни, използвайки директивата ng-repeat.

  1. Първо създаваме променлива, наречена „урок“ и й присвояваме няколко двойки ключ-стойност в една стъпка. Всяка двойка ключ-стойност ще се използва като данни при показване на таблицата. След това променливата на урока се присвоява на обекта на обхвата, така че да може да бъде достъпен от нашия изглед.
  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 = angular.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 реда данни, както трябва от горния пример.

Първо трябва да се уверим, че е налице следното предварително условие

Инсталирайте професионалистаtractor библиотека чрез npm. Това може да се направи чрез изпълнение на следния ред в командния ред

npm install -g protractor

Кодът за нашия тест ще бъде както е показано по-долу.

Кодът ще бъде в отделен файл, наречен CompleteTest.js, който ще бъде поставен в тестовата папка. Кодът по-долу прави следните ключови неща

  1. Функцията на браузъра се предоставя от професионалистаtractor библиотека и приема, че нашето AngularJS приложение (с показания по-горе код) работи на нашия сайт URL – http://localhost:8080/Guru99 /
  2. var list = element.all(by.repeater('ptutor in tutorial')); -Този ред код всъщност извлича директивата ng-repeat, която е попълнена от кода 'ptutor in tutorial'. Element и by.repeater са специални ключови думи, предоставени от protractor библиотека, която ни позволява да получим подробности за директивата ng-repeat.
  3. очаквам (list.count()).toEqual(3); – И накрая, ние използваме функцията за очакване, за да видим, че наистина получаваме 3 елемента, които се попълват в нашата таблица в резултат на директивата ng-repeat.
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 и ще даде същия резултат за преминаване, както беше показано в предишната тема.

Карма срещу Жасмин срещу ПроtracТор: Ключови разлики

Трите инструмента, използвани на тази страница, често се бъркат, защото се появяват в един и същ команден ред. Всеки един заема различен слой от стека за тестване, както става ясно от таблицата по-долу.

Параметър Карма жасмин професионалистtracTor
категория Тест бегач Рамка на спецификациите Рамка за цялостна автоматизация
Основна работа Стартира браузъри и отчита резултати Предоставя „описвам“, „то“ и „очаквам“ Управлява живо приложение в реален браузър
Ниво на тест Единица и интеграция Единица и интеграция От край до край
Изисква работещ сървър Не Не Да
файл за конфигуриране karma.conf.js Няма, работи вътре в бегач заtractor.conf.js
Актуално състояние Остаряло, само поддръжка Активно поддържан Пенсиониран през август 2023 г.

Накратко, Жасмин пише теста, Карма го изпълнява, а Про...tractor разширява същия синтаксис на Jasmine до напълно рендирана страница.

Най-добри практики за AngularJS модулно тестване

Малък набор от навици поддържа AngularJS пакета бърз и надежден, докато приложението расте.

  1. Тествайте по едно устройство наведнъж. Заредете само тествания модул вътре в beforeEach и имитирайте всеки сътрудник, така че всеки неуспех да сочи към един файл.
  2. Никога не се обаждайте на истински бекенд. Използвайте услугата $httpBackend от angular-mocks, за да върнете предварително зададени отговори. Тестовете след това се изпълняват офлайн и дават идентични резултати на всяка машина.
  3. Поддържайте имената на спецификациите поведенчески. Име като „връща 5 при инициализация на контролера“ се чете по-добре в отчет, отколкото „test1“.
  4. Винаги промивайте цикъла на смилане. Извикайте $rootScope.$digest() след промяна на данните за обхвата, в противен случай обвързванията и наблюдателите никога не се актуализират и твърденията се провалят по грешна причина.
  5. Измерете покритието, но го преценете внимателно. Добавете karma-coverage, за да видите непроверени клонове. Високото покритие със слаби твърдения все още крие дефекти.
  6. Стартирайте пакета в режим на непрекъсната интеграция. Използвайте headless стартер за Chrome, така че едни и същи спецификации да се изпълняват при всеки commit, а не само на машина на разработчик.

Прилагането на тези правила превръща горните примери от изолирани демонстрации в предпазна мрежа за регресионна защита за наследена кодова база AngularJS. За по-широка картина вижте Урок по AngularJS серия.

Въпроси и Отговори

Модулът, съдържащ този доставчик, не е зареден. Добавете го в beforeEach(module('yourModule')) и проверете дали angular-mocks.js е посочен в karma.conf.js след angular.js, в противен случай инжекторът не може да разреши зависимостта.

Инсталирайте karma-chrome-launcher и задайте опцията на браузъра на ChromeHeadless в karma.conf.js. След това пакетът работи в рамките на непрекъснати интеграционни канали и контейнери, където няма наличен сървър за показване.

Да. Асистентите за кодиране с изкуствен интелект четат контролер и изготвят спецификации на Jasmine с фалшиви обхвати и съпоставители. RevПрегледайте внимателно резултата, защото генерираните твърдения често преформулират имплементацията, вместо да проверяват предвиденото поведение.

Да. Инструментите с изкуствен интелект превеждат спецификациите на Jasmine в синтаксис на Jest или Vitest и маркират извиквания на Angular-mocks, които нямат директен еквивалент. Ръчната проверка остава от съществено значение, тъй като моделите за инжектиране на зависимости рядко конвертират чисто.

Повечето екипи се стремят към седемдесет до осемдесет процента покритие на отчетите за контролери и услуги. Преследването на по-висока цифра обикновено означава тестване на шаблони и библиотеки на трети страни, което добавя разходи за поддръжка, без да се откриват реални дефекти.

Обобщете тази публикация с: