Статьи

Начало работы с QUnit

Тестирование программного обеспечения — это процесс оценки части программного обеспечения для выявления различий между ожидаемыми и фактическими результатами для данного набора входных данных. Тестирование, в частности модульное тестирование, должно стать неотъемлемой частью жизни каждого разработчика. К сожалению, многие разработчики, похоже, боятся этой деятельности.

В JavaScript есть много фреймворков, из которых мы можем выбрать тестирование нашей базы кода. Некоторыми примерами являются Mocha , Selenium и QUnit . В этой статье я познакомлю вас с QUnit. QUnit — это среда модульного тестирования, разработанная и поддерживаемая командой jQuery, которая является той же командой, что и такие проекты, как jQuery и jQuery UI.

Настройка QUnit

Одной из основных причин, почему многие разработчики используют QUnit, является его простота использования. Начать с этой структуры очень просто, и основные концепции можно понять за несколько часов.

Очевидным первым шагом для использования QUnit является его загрузка. Есть несколько способов сделать это: загрузить его вручную с веб-сайта, используя CDN, используя Bower или npm. Я предлагаю, чтобы, если вы не разрабатываете простую живую демоверсию, вам не следует полагаться на CDN для тестирования своего кода. Итак, придерживайтесь других вариантов.

Для этой статьи я не хочу устанавливать никаких предварительных условий (прочитайте Bower и npm), поэтому мы будем использовать первый метод. Поэтому перейдите на веб-сайт QUnit и загрузите последнюю версию как файла JavaScript (с именем qunit-1.14.0.js), так и файла CSS (с именем qunit-1.14.0.css).

Поместите их в папку, где вы также создадите index.html В этом файле мы разместим код HTML, показанный на домашней странице сайта, который я повторяю ниже для вашего товара.

 <!DOCTYPE html>
<html>
   <head>
      <meta charset="utf-8">
      <title>QUnit Example</title>
      <link rel="stylesheet" href="//code.jquery.com/qunit/qunit-1.14.0.css">
   </head>
   <body>
      <div id="qunit"></div>
      <div id="qunit-fixture"></div>
      <script src="//code.jquery.com/qunit/qunit-1.14.0.js"></script>
      <script src="tests.js"></script>
   </body>
</html>

Как видите, этот код использует CDN для включения файлов CSS и JavaScript. Таким образом, вы должны обновить ссылки, чтобы включить файлы, которые вы ранее скачали.

В разметке вы можете видеть, что есть пара <div> Первый, имеющий qunit Второй <div>qunit-fixture Этот элемент позволяет разработчику тестировать код, который добавляет, редактирует или удаляет элементы из DOM, не беспокоясь об очистке DOM после каждого теста. Если вы поместите элементы, созданные кодом, в этот <div>

Наконец, у нас есть файл tests.js Мой совет — использовать файл для хранения ваших тестов при работе над реальным проектом. В живых демонстрациях, которые я создал для этого урока, я использовал JSBin, который, конечно, не позволяет загружать файлы. Поэтому в демоверсиях вы увидите, что я добавил код тестов.

Теперь, когда вы знаете значение каждой части разметки, откройте страницу index.html

Если все прошло хорошо, вы должны увидеть интерфейс, как показано в демонстрационном примере ниже, который также доступен как JSBin :

На данном этапе единственной важной частью этого интерфейса для нас является раздел, в котором показано время, которое QUnit потратил на обработку тестов, количество определенных утверждений, а также количество пройденных и неудачных тестов. Демонстрация выше показывает, что мы не определили ни одного теста. Давайте это исправим.

Как создать тест с помощью QUnit

QUnit предлагает два метода для создания нового теста: QUnit.test()QUnit.asyncTest() Первый используется для тестирования кода, который выполняется синхронно, а второй — для проверки асинхронного кода. В этом разделе я опишу, как создавать тесты для синхронного кода.

Подпись метода QUnit.test()

 QUnit.test(name, testFunction)

Первый параметр name Второй параметр, testFunction Каркас передает этой функции аргумент, который раскрывает все методы утверждения QUnit.

Поместив это описание в код, мы можем обновить файл tests.js

 QUnit.test('My first test', function(assert) {
   // Assertions here...
});

Этот код создает новый тест, идентифицируемый строкой «Мой первый тест» и функцией с пустым телом. Добавление теста без каких-либо утверждений не имеет никакого значения. Чтобы исправить эту проблему, мы должны изучить методы утверждения, доступные в QUnit.

Методы утверждения QUnit

Утверждения являются ядром тестирования программного обеспечения. Они — часть, которая позволяет нам проверить, что наш код работает должным образом. В QUnit у нас есть несколько методов для проверки этих ожиданий. Доступ к ним можно получить с помощью параметра, переданного в функцию метода QUnit.test()assert

Список ниже суммирует доступные методы вместе с их подписью и назначением:

  • deepEqual(value, expected[, message]) Утверждение проходит, если valueexpected
  • equal(value, expected[, message])valueexpected==
  • notDeepEqual(value, expected[, message])deepEqual()
  • notEqual(value, expected[, message])equal()
  • propEqual(value, expected[, message]) Утверждение проходит, если все свойства и значения идентичны;
  • strictEqual(value, expected[, message])valueexpected===
  • notPropEqual(value, expected[, message])propEqual()
  • notStrictEqual(value, expected[, message])strictEqual()
  • ok(value[, message]
  • throws(function [, expected ] [, message ])

Значение параметров, принятых этими методами, описано ниже:

  • value
  • expected В случае метода throws()Error (экземпляр), функция Error (конструктор), RegExp, который соответствует (или частично соответствует) представлению String, или функция обратного вызова, которая должна возвращать true, чтобы передать утверждение проверить ;
  • message
  • function

Теперь, когда вы знаете доступные методы и параметры, пришло время посмотреть код. Вместо того, чтобы писать несколько тестов для одной функции, я постараюсь воспроизвести более реалистичный пример. Любые тесты, которые я покажу вам, должны рассматриваться как полный набор тестов, но они должны дать вам конкретное представление о том, с чего начать.

Чтобы написать упомянутые тесты, нам нужно определить код для тестирования. В этом случае я собираюсь определить литерал объекта следующим образом:

 var App = {
   max: function() {
      var max = -Infinity;
      for (var i = 0; i < arguments.length; i++) {
         if (arguments[i] > max) {
            max = arguments[i];
         }
      }

      return max;
   },
   isOdd: function(number) {
      return number % 2 !== 0;
   },
   sortObj: function(array) {
      array.sort(function(a, b) {
         var date1 = new Date(a.timestamp).getTime();
         var date2 = new Date(b.timestamp).getTime();

         if (date1 < date2) {
            return -1;
         } else if (date1 === date2) {
            return 0;
         } else {
            return 1;
         }
      });
   }
};

Как видите, мы определили литерал объекта, содержащий три функции: max()isOdd()sortObj() Первый принимает произвольное количество аргументов и возвращает максимум. isOdd() sortObj()timestamp

Возможный набор тестов для этих функций показан ниже:

 QUnit.test('max', function (assert) {
    assert.strictEqual(App.max(), -Infinity, 'No parameters');
    assert.strictEqual(App.max(3, 1, 2), 3, 'All positive numbers');
    assert.strictEqual(App.max(-10, 5, 3, 99), 99, 'Positive and negative numbers');
    assert.strictEqual(App.max(-14, -22, -5), -5, 'All positive numbers');
});

QUnit.test('isOdd', function (assert) {
    assert.ok(App.isOdd(5), '5 is odd');
    assert.ok(!App.isOdd(2), '5 is not odd');
    assert.ok(!App.isOdd(0), '0 is not odd');
    assert.throws(function () {
        App.isOdd(null);
    },
        /The given argument is not a number/,
        'Passing null raises an Error');
    assert.throws(function () {
        App.isOdd([]);
    },
    new Error('The given argument is not a number'),
        'Passing an array raises an Error');
});


QUnit.test('sortObj', function (assert) {
    var timestamp = Date.now();

    var array = [{
        id: 1,
        timestamp: timestamp
    }, {
        id: 3,
        timestamp: timestamp + 1000
    }, {
        id: 11,
        timestamp: timestamp - 1000
    }];

    App.sortObj(array);

    assert.propEqual(array, [{
        id: 11,
        timestamp: timestamp - 1000
    }, {
        id: 1,
        timestamp: timestamp
    }, {
        id: 3,
        timestamp: timestamp + 1000
    }]);
    assert.notPropEqual(App.sortObj(array), array, 'sortObj() does not return an array');
    assert.strictEqual(App.sortObj(array), undefined, 'sortObj() returns
});

Первый созданный тест идентифицируется строкой «max». В этом тесте вы можете увидеть четыре утверждения, которые используют метод strictEqual() Мы используем этот метод вместо equal()

 assert.equal(App.max(0, true), 1);

Внутри теста мы проверяем несколько разных типов ввода. Что я пытаюсь предложить в этом тесте, так это попытаться охватить наибольшее количество возможных ситуаций: без параметров, все положительные числа, все отрицательные числа, смешанные случаи. Я не охватил все возможности, но это хорошее начало.

Второй тест, идентифицируемый строкой isOdd, показывает использование ok()throws() Первый полезен, когда вам нужно проверить функции, которые возвращают логическое значение, такое как isOdd() Вы также можете увидеть метод throws() Вероятно, наиболее интересной частью утверждений с использованием throws() На самом деле, я использовал как регулярное выражение, так и экземпляр Error.

Третий и последний тест, идентифицируемый строкой «sortObj», приводит в действие другие методы утверждения. Первое утверждение использует propEqual()sortObj() В этом тесте метод deepEqual() Я мог бы не использовать strictEqual()не один и тот же объект, то есть два объекта, указывающие на один и тот же адрес памяти.
Второе утверждение немного наивно и служит только для демонстрации использования notPropEqual() Это наивно, потому что мы уже более точно проверяем ожидаемое значение, используя метод strictEqual()

Вам понравился пример? Вы узнали что-то новое помимо подписи методов? Я надеюсь, что это так. Прежде чем закончить этот урок, есть еще одна вещь для обсуждения.

Установка ожиданий

При создании теста рекомендуется установить количество утверждений, которые мы ожидаем выполнить. При этом тест не пройден, если одно или несколько утверждений не выполнены. Платформа QUnit предлагает для этого метод wait expect() Этот метод особенно полезен при работе с асинхронным кодом, но лучше использовать его также при тестировании синхронных функций. Сигнатура метода expect()

 expect(assertionsNumber)

Где параметр assertionsNumber

Зная эту новую концепцию, давайте обновим наши тесты, чтобы установить количество утверждений, которые мы ожидаем выполнить:

 QUnit.test('max', function(assert) {
   expect(4);
   
   // Assertions here...
});

QUnit.test('isOdd', function(assert) {
   expect(5);
   
   // Assertions here...
});

QUnit.test('sortObj', function(assert) {
   expect(3);
   
   // Assertions here...
});

Демонстрационная версия кода, в том числе вызов метода wait expect()доступна в виде JSBin .

Вывод

В этом уроке я познакомил вас с волшебным миром тестирования, и особенно с тем, как тестировать код JavaScript с помощью QUnit. Мы видели, как легко настроить инфраструктуру QUnit и какие методы она предоставляет для тестирования синхронных функций. Кроме того, вы изучили набор функций утверждений, которые фреймворк предлагает для тестирования нашего кода. Наконец, я упомянул о важности установки количества утверждений, которые мы ожидаем выполнить, и о том, как мы можем установить их с помощью метода expect() Надеюсь, вам понравилась статья, и вы подумаете об интеграции QUnit в свои проекты.