Модульне тестування 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.
  • 📁 Правило конфігурації: Масив files повинен містити 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 має настільки блискучий функціонал для тестування коду AngularJS, що використання саме цього фреймворку є сенсом.

⚠️ Примітка до версії: AngularJS (версія 1.x) офіційно завершив свою підтримку 31 грудня 2021 року, а Pro...tracПідтримку Tor було припинено у серпні 2023 року. Робочий процес на цій сторінці залишається дійсним для підтримки існуючих програм AngularJS 1.x. Нові проекти повинні використовувати сучасний Angular з підтримуваним на даний момент раннером.

Введення та встановлення фреймворку Karma

Карма - це а засіб автоматизації тестування створено командою AngularJS за адресою GoogleПершим кроком для використання Karma є встановлення Karma. Karma встановлюється через npm (менеджер пакетів, який використовується для легкого встановлення модулів на локальній машині).

Установка Карми

Встановлення Karma через npm виконується в два етапи.

Крок 1) Виконайте наведений нижче рядок із командного рядка

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

де,

  1. npm — це утиліта командного рядка для менеджера пакетів вузлів, яка використовується для встановлення користувацьких модулів на будь-якій машині. Вона постачається з Node.js.
  2. Параметр install повідомляє утиліті командного рядка npm про необхідність інсталяції.
  3. У командному рядку вказано 3 бібліотеки, необхідні для роботи з karma.
    • karma — основна бібліотека, яка використовуватиметься для тестування.
    • karma-chrome-launcher — це окрема бібліотека, яка дозволяє браузеру chrome розпізнавати команди karma.
    • karma-jasmine – це встановлює jasmine, який є залежною структурою для Karma.

Крок 2) Наступним кроком буде встановлення утиліти командного рядка karma. Це потрібно для виконання команд рядка 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. Папка tests міститиме всі модульні тести.

💡 Порада: Порядок має значення в масиві файлів. 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. Це вікно показує виконання всіх тестів, які визначені в структурі karma.
  2. Тут ви можете побачити, що показано опис виконаного тесту, тобто «Зразок тесту».
  3. Далі ви можете побачити, що виконується сам тест, який має назву «Умова вірна».
  4. Зауважте, що, оскільки всі тести мають зелену піктограму «ОК», яка символізує, що всі тести пройдено.

Що таке Jasmine в модульному тестуванні AngularJS?

Karma вирішує, де запускаються тести, а Jasmine — як вони пишуться. Jasmine — це фреймворк специфікацій, керований поведінкою, який надає словник, що використовується в кожному прикладі на цій сторінці, тому адаптер karma-jasmine встановлено разом із раннером.

Жасмін робить внесок у чотири складові:

  • опис(): Групує пов'язані специфікації в набір та приймає зрозумілий опис тестованого пристрою.
  • це(): Оголошує одну специфікацію. Назва повинна вказувати на поведінку, що перевіряється, а не на метод, що викликається.
  • expect() з порівняннями: Порівнює фактичне значення з очікуваним. Звичайні методи зіставлення включають toBe, toEqual, toContain та toBeDefined.
  • beforeEach() та afterEach(): Виконуйте налаштування та демонтаж до та після кожної специфікації, що забезпечує незалежність кожного тесту.

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']
  • Параметр «files» в основному повідомляє Karma про всі файли, які потрібні для виконання тестів.
  • Файли angular.js та angular-mocks.js необхідні для запуску модульних тестів AngularJS.
  • Файл index.js міститиме наш код для контролера
  • Папка test міститиме всі наші тести AngularJS

Нижче наведено наш код AngularJS, який буде збережено як файл Index.js у папці test нашого застосунку.

Наведений нижче код просто виконує такі дії

  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, який буде розміщено в папці test. Наведений нижче код виконує лише такі ключові речі

  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, який буде розміщено в папці test. Наведений нижче код виконує лише такі ключові речі

  1. Функція beforeEach – ця функція використовується для завантаження нашого модуля AngularJS під назвою «sampleApp» перед тестовим запуском.
  2. Для компіляції директиви використовується сервіс $compile. Цей сервіс є обов'язковим і його потрібно оголосити, щоб AngularJS міг використовувати його для компіляції нашої власної директиви.
  3. Об'єкт $rootScope – це основна область видимості будь-якого застосунку AngularJS. Ми вже розглядали об'єкт $scope контролера в попередніх розділах. Об'єкт $scope є дочірнім об'єктом об'єкта $rootScope. Причина, чому він оголошується тут, полягає в тому, що ми вносимо зміни до фактичного тегу HTML у DOM за допомогою нашої власної директиви. Отже, нам потрібно використовувати сервіс $rootScope, який фактично прослуховує або знає, коли відбуваються будь-які зміни в HTML-документі.
  4. var елемент = $compile(" ”)($rootScope) – Це використовується для перевірки, чи наша директива вводиться належним чином. Директива зареєстрована з назвою guru99, що складається з літер верблюжого регістру, тому AngularJS відповідає елементу з нижнім регістром у розмітці. Отже, цей оператор використовується для виконання цієї перевірки.
  5. expect(element.html()).toContain(“Це тестування AngularJS”) – Це використовується для вказівки функції expect знайти елемент (у нашому випадку тег 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. Спочатку ми створюємо змінну під назвою «tutorial» і призначаємо їй кілька пар ключ-значення за один крок. Кожна пара ключ-значення використовуватиметься як дані під час відображення таблиці. Змінна підручника потім призначається об’єкту scope, щоб до нього можна було отримати доступ із нашого подання.
  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 рядки даних, як і повинно бути з наведеного вище прикладу.

Спочатку нам потрібно переконатися, що наступні передумови є на місці

Встановіть професіоналаtracбібліотеку tor через npm. Це можна зробити, виконавши наведений нижче рядок у командному рядку

npm install -g protractor

Код для нашого тесту буде таким, як показано нижче.

Код буде в окремому файлі CompleteTest.js, який буде розміщено в папці test. Наведений нижче код виконує лише такі ключові речі

  1. Функцію браузера забезпечує професіоналtracбібліотека tor та припускає, що наш AngularJS-застосунок (з кодом, показаним вище) працює на нашому сайті URL – http://localhost:8080/Guru99 /
  2. var list = element.all(by.repeater('ptutor in tutorial')); -Цей рядок коду фактично отримує директиву ng-repeat, яка заповнюється кодом 'ptutor in tutorial'. Element та by.repeater – це спеціальні ключові слова, надані розробником.tracБібліотека tor, яка дозволяє нам отримати детальну інформацію про директиву 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Тор: Ключові відмінності

Три інструменти, що використовуються на цій сторінці, часто плутають, оскільки вони відображаються в одному командному рядку. Кожен з них займає окремий рівень стеку тестування, як видно з таблиці нижче.

Параметр Карма жасмин Профіtracтор
Категорія Випробувальний бігун Структура специфікацій Комплексна система автоматизації
Основна робота Запускає браузери та повідомляє про результати Надає опис, це та очікування Запускає активну програму в реальному браузері
Тестовий рівень Одиниця та інтеграція Одиниця та інтегрування Кінець в кінець
Потрібен працюючий сервер Немає Немає Так
Файл конфігурації karma.conf.js Ні, він працює всередині бігунка дляtractor.conf.js
Поточний статус Застаріло, лише для технічного обслуговування Активно обслуговується Вийшов на пенсію у серпні 2023 року

Коротше кажучи, Жасмін пише тест, Карма його виконує, а Про...tractor розширює той самий синтаксис Jasmine на повністю відрендерену сторінку.

Найкращі практики для модульного тестування AngularJS

Невеликий набір звичок забезпечує швидкість та надійність AngularJS-пакету в міру зростання застосунку.

  1. Тестуйте один пристрій за раз. Завантажте лише модуль, що тестується, всередину beforeEach та змоделюйте кожного співавтора, щоб у разі помилки вказував на один файл.
  2. Ніколи не телефонуйте справжньому бекенду. Використовуйте сервіс $httpBackend з angular-mocks для повернення шаблонних відповідей. Тести потім запускаються офлайн та дають однакові результати на кожній машині.
  3. Зберігайте поведінкові назви специфікацій. Назва типу «повертає 5 під час ініціалізації контролера» читається у звіті краще, ніж «test1».
  4. Завжди промивайте цикл перетравлення. Викличте $rootScope.$digest() після зміни даних області видимості, інакше прив'язки та спостерігачі ніколи не оновлюватимуться, а твердження завершаться невдачею з неправильної причини.
  5. Вимірюйте охоплення, але оцінюйте його ретельно. Додайте покриття карми, щоб побачити непротестовані гілки. Високе покриття зі слабкими твердженнями все ще приховує дефекти.
  6. Запустіть пакет у режимі безперервної інтеграції. Використовуйте headless-лаунчер Chrome, щоб ті самі специфікації виконувалися для кожного коміту, а не лише на машині розробника.

Застосування цих правил перетворює наведені вище приклади з ізольованих демонстрацій на захисну сітку регресії для застарілої кодової бази 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, які не мають прямого еквівалента. Ручна перевірка залишається важливою, оскільки шаблони впровадження залежностей рідко конвертуються коректно.

Більшість команд прагнуть охопити контролерами та сервісами від сімдесяти до вісімдесяти відсотків інструкцій. Прагнення до вищого показника зазвичай означає тестування шаблонів та сторонніх бібліотек, що збільшує витрати на обслуговування без виявлення реальних дефектів.

Підсумуйте цей пост за допомогою: