В последнее время я освежал некоторые из моих навыков Javascript и подумал, что, возможно, также пришло время изучить структуру тестирования Javascript. К сожалению, тестирование всегда кажется второстепенным. Это похоже на кучу дополнительной работы, которая не приближает вас к вашей цели - конечному продукту. Однако, если вы сначала выполните часть этой работы, это может избавить вас от многих разочарований в будущем. Это устраняет любые сомнения в том, что ваше приложение работает должным образом. Это также избавляет вас от поломки, когда вам нужно внести изменения. Конечно, с правильными тестами!

В последнее время я слышал, как люди упоминают Mocha.js, поэтому подумал, что это хорошее место для начала.

Взглянув на домашнюю страницу Mocha.js, я вижу, что там есть раздел Начало работы. Звучит превосходно.

Шаг первый - установить Mocha через NPM либо глобально, либо как зависимость от проекта. Я выбрал глобальную установку

npm install --global mocha

Однако это привело к ошибке разрешений.

Хммм… Хочу ли я прямо сейчас спуститься в кроличью нору разрешений? Нет. А как насчет попытки установки с Yarn?

Ладно, выглядит лучше. Давай продолжаем.

Следующие шаги в разделе «Установка» - это установка mocha, создание тестового каталога и файла test.js. Я сделал это в другом порядке, вместо этого сначала создал тестовый каталог, а затем установил мокко внутри этого каталога.

mkdir mocha-test
npm install mocha

На этом этапе я получил сообщение об отсутствии файла package.json. Хм….

Я решил перейти к следующему шагу и запустить мокко, чтобы посмотреть, работает ли эта часть.

./node_modules/mocha/bin/mocha

Да, похоже, это так.

Следующим шагом в разделе «Установка» является настройка сценария в файле package.json, чтобы вы могли запускать мокко со следующим кодом:

npm test

Однако у меня не было файла package.json в этом каталоге, как указано в предыдущей ошибке. Поэтому я решил создать его.

npm init

Это запустит процесс создания файла package.json. Вам будет задан ряд вопросов о файле, и в конце файл будет создан. Я просто взял ответы по умолчанию, поэтому точкой входа был мой файл test.js. Итак, мой файл package.json уже соответствует тому, который указан в разделе «Установка».

"scripts": {
    "test": "mocha"
  }

Теперь я могу просто запустить npm test, и тесты в файле test.js будут запущены.

Здорово! Mocha запущен и делает то, что должен делать. Теперь я хотел бы немного покопаться в реальном сценарии тестирования и посмотреть, что там происходит.

var assert = require('assert');
describe('Array', function() {
  describe('#indexOf()', function() {
    it('should return -1 when the value is not present', function() {
      assert.equal(-1, [1,2,3].indexOf(4));
    });
  });
});

Это ОЧЕНЬ похоже на тестирование rspec, которое я использовал с Ruby, так что, возможно, это будет не так уж плохо.

Начнем с первой строчки:

var assert = require('assert')

Assert - это модуль NPM, который предоставляет набор тестов утверждения. Эти тесты предназначены для работы в паре со средой тестирования. В данном случае Mocha. Итак, эта строка требует этот модуль утверждения и назначает его переменной assert, которая используется позже в сценарии.

Далее идут describe строк. Они служат нескольким целям. Во-первых, они помогают сгруппировать ваши тесты в логические части, чтобы вы тестировали только одну вещь за раз. Кроме того, они обеспечивают лучшую читаемость результатов тестирования. Давайте еще раз посмотрим на результат теста.

Как видите, результат теста имеет два уровня. Первый - «Массив», а второй - «#indexOf ()». Обе они соответствуют двум describe функциям в тестовом сценарии.

В качестве примера я удалил одну из функций описания и снова запустил тест.

Теперь мы просто видим результат "#indexOf ()". Теперь мы понятия не имеем, что этот тест проводится с «Массивом». Если у вас было несколько тестов «#indexOf ()», у вас могут возникнуть проблемы с определением, что есть что.

Теперь о блоке it. Здесь вы можете написать собственно тест. Первый аргумент блока it - это описание теста и то, что вы увидите в результатах. Следующий аргумент - функция с тестом.

assert.equal(-1, [1,2,3].indexOf(4));

В этом тесте используется переменная assert, заданная в первой строке. Он вызывает метод equal против предоставленных аргументов. Первый аргумент (-1) - это фактическое значение теста. В этом случае, если вы запустите метод .indexOf(4) для массива [1,2,3], вы получите «-1».

Второй аргумент для метода equal - это ожидаемое значение. В данном случае это результат вызова метода .indexOf() для массива, который равен -1.

Поскольку этот тест всегда дает -1 и это ожидаемый результат, тест проходит. Это снова отражается на результате в терминале.

В этом примере я изменил одну вещь в тестовой строке, чтобы показать, что происходит, когда тест не проходит. Я изменил строку assert на эту:

assert.equal(-1, [1,2,3].indexOf(3));

Теперь ожидаемый результат - «2».

Теперь, когда наш фактический результат равен -1, а ожидаемый результат равен 2, тест не пройдёт.

Как вы можете видеть, на странице результатов указываются ожидаемые и фактические значения, указывается, что они не равны, а затем, где в тестовом файле вы можете найти это (строка 5).

Чтобы немного расширить свои границы, я решил написать свой собственный тест. Это довольно просто, но показывает немного больше того, что можно сделать с помощью этого тестирования.

Вот тест, который я написал:

describe('Function', function(){
  describe('#doubler', function(){
    it('should return the double of the number provided', function(){
      var num = 2;
      var doubler = function(num){
        return num * 2
      };
      
      assert.equal(4, doubler(2))
    });
  });
});

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

Этот тест проходит со следующим результатом:

Каждый тест вложен под собственным заголовком и дает хорошее описание того, что тест пытается выполнить.