Работа с CommonJS

CommonJS — это спецификация для модульной системы в JavaScript, которая предназначена для использования в серверных средах, таких как Node.js. Она определяет стандарт для организации кода в виде отдельных модулей с их импортом и экспортом, что обеспечивает более удобную работу с кодом, масштабируемость и повторное использование.

В контексте тестирования с Mocha, CommonJS является основным способом работы с модулями. Mocha поддерживает CommonJS из коробки, что позволяет организовывать тесты, разделяя их на несколько файлов и модуляризуя их для удобства и простоты сопровождения.

Структура модулей в CommonJS

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

Экспортирование модулей

Для того чтобы экспортировать функциональность из модуля в CommonJS, используется объект module.exports. Это позволяет другим файлам подключать и использовать функциональность, определённую в другом модуле.

Пример:

// utils.js
function add(a, b) {
  return a + b;
}

module.exports = {
  add
};

В этом примере в модуле utils.js определяется функция add, которая экспортируется с помощью module.exports. Таким образом, другие модули могут её использовать.

Импортирование модулей

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

Пример:

// test.js
const utils = require('./utils');

console.log(utils.add(2, 3)); // 5

Здесь файл test.js использует функцию add из модуля utils.js, импортируя её через require.

Использование CommonJS в Mocha

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

Подключение и организация тестов

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

Пример:

// utils.test.js
const assert = require('assert');
const utils = require('./utils');

describe('Utils', function() {
  describe('#add()', function() {
    it('должен возвращать правильный результат', function() {
      assert.strictEqual(utils.add(2, 3), 5);
    });
  });
});

В этом примере тесты для функции add из модуля utils.js находятся в файле utils.test.js. Используя describe и it, можно организовать тесты в структуру, которая будет легко расширяться.

Организация тестов в модули

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

Пример:

// add.test.js
const assert = require('assert');
const utils = require('./utils');

describe('add', function() {
  it('должен корректно складывать два числа', function() {
    assert.strictEqual(utils.add(1, 2), 3);
  });
  it('должен возвращать отрицательное число для отрицательных аргументов', function() {
    assert.strictEqual(utils.add(-1, -2), -3);
  });
});

Затем, основной файл тестирования может выглядеть следующим образом:

// test.js
require('./add.test');
require('./subtract.test'); // добавляем другие файлы тестов по мере необходимости

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

Использование хелперов и утилит в тестах

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

Пример:

// helpers.js
function mockDate(dateString) {
  return new Date(dateString);
}

module.exports = {
  mockDate
};
// test.js
const helpers = require('./helpers');
const assert = require('assert');

describe('Date testing', function() {
  it('должен работать с мокированными датами', function() {
    const mock = helpers.mockDate('2022-01-01');
    assert.strictEqual(mock.getFullYear(), 2022);
  });
});

В этом примере модуль helpers.js экспортирует функцию mockDate, которая используется в тестах для мокирования дат. Это позволяет избежать дублирования кода и делать тесты более читаемыми.

Mocha и асинхронные тесты

В Mocha можно легко работать с асинхронными тестами, используя возможности CommonJS. Mocha поддерживает асинхронные тесты с использованием коллбеков, промисов и async/await. Чтобы Mocha знал, что тест асинхронный, необходимо либо передать коллбек в функцию it, либо вернуть промис, либо использовать async/await.

Пример с коллбеком:

const assert = require('assert');
const utils = require('./utils');

describe('Utils async', function() {
  it('должен корректно складывать числа асинхронно', function(done) {
    utils.addAsync(2, 3, function(result) {
      assert.strictEqual(result, 5);
      done();
    });
  });
});

Пример с промисом:

describe('Utils async', function() {
  it('должен корректно складывать числа асинхронно', function() {
    return utils.addAsync(2, 3).then(result => {
      assert.strictEqual(result, 5);
    });
  });
});

Пример с async/await:

describe('Utils async', function() {
  it('должен корректно складывать числа асинхронно', async function() {
    const result = await utils.addAsync(2, 3);
    assert.strictEqual(result, 5);
  });
});

В каждом из этих примеров Mocha будет корректно обрабатывать асинхронные операции и ожидать их завершения до того, как тест будет завершён.

Заключение

Использование CommonJS в Mocha предоставляет мощный инструмент для организации тестов и упрощения работы с большим количеством тестов и вспомогательных функций. Разделение кода на модули, использование экспорта и импорта позволяет сделать тесты более читаемыми и поддерживаемыми. Mocha поддерживает работу с асинхронными тестами, что даёт возможность тестировать асинхронные функции и логику с использованием различных методов, таких как коллбеки, промисы и async/await.