Mocha предоставляет возможность организовывать тесты в структуру, которая улучшает читаемость и поддерживаемость кода. Это достигается благодаря использованию различных типов блоков и возможностей для группировки тестов, что позволяет не только упорядочить тесты, но и установить определённые зависимости и контексты выполнения. В этой главе рассмотрим, как создавать и эффективно использовать композицию тестовых наборов.
describeДля логической группировки тестов в Mocha используется блок
describe. Этот блок позволяет сгруппировать несколько
тестов, которые могут быть частью одной функциональной области или
проверять одну особенность приложения. Важно, что блоки
describe могут быть вложенными, что даёт возможность
создавать иерархическую структуру тестов.
Пример:
describe('Тестирование калькулятора', function() {
describe('Сложение', function() {
it('должно складывать два числа', function() {
const result = калькулятор.сложить(1, 2);
assert.equal(result, 3);
});
});
describe('Вычитание', function() {
it('должно вычитать два числа', function() {
const result = калькулятор.вычесть(5, 3);
assert.equal(result, 2);
});
});
});
Здесь мы видим два блока describe, которые группируют
тесты по операциям калькулятора — сложение и вычитание. Такой подход
помогает логически разделить тесты и облегчить их поддержку.
describeMocha позволяет использовать вложенные блоки describe,
что даёт возможность создавать сложные структуры тестов. Например, когда
необходимо описать поведение в разных условиях или с разными данными,
вложенные блоки помогут организовать тесты.
Пример:
describe('Тестирование калькулятора', function() {
describe('Когда числа положительные', function() {
it('должно складывать два числа', function() {
const result = калькулятор.сложить(1, 2);
assert.equal(result, 3);
});
it('должно вычитать два числа', function() {
const result = калькулятор.вычесть(5, 3);
assert.equal(result, 2);
});
});
describe('Когда одно из чисел отрицательное', function() {
it('должно складывать два числа', function() {
const result = калькулятор.сложить(-1, 2);
assert.equal(result, 1);
});
it('должно вычитать два числа', function() {
const result = калькулятор.вычесть(5, -3);
assert.equal(result, 8);
});
});
});
В этом примере добавлены вложенные блоки describe, чтобы
протестировать калькулятор при разных типах входных данных — с
положительными и отрицательными числами. Это упрощает организацию
тестов, позволяя легко изменять и добавлять новые сценарии.
before, after, beforeEach,
afterEachЧтобы управлять состоянием тестов, Mocha предоставляет несколько
хуков: before, after, beforeEach
и afterEach. Эти хуки позволяют выполнить код перед или
после выполнения тестов или каждого теста в группе.
before — выполняется один раз перед
всеми тестами в блоке.after — выполняется один раз после
всех тестов в блоке.beforeEach — выполняется перед каждым
тестом.afterEach — выполняется после каждого
теста.Пример:
describe('Тестирование калькулятора', function() {
let калькулятор;
before(function() {
калькулятор = new Calculator();
});
after(function() {
// Очистка после всех тестов
калькулятор = null;
});
beforeEach(function() {
// Инициализация перед каждым тестом
калькулятор.reset();
});
describe('Сложение', function() {
it('должно складывать два числа', function() {
const result = калькулятор.сложить(1, 2);
assert.equal(result, 3);
});
});
describe('Вычитание', function() {
it('должно вычитать два числа', function() {
const result = калькулятор.вычесть(5, 3);
assert.equal(result, 2);
});
});
});
В этом примере:
before создаётся новый экземпляр
калькулятора.after происходит очистка.beforeEach калькулятор сбрасывается перед
каждым тестом, чтобы избежать зависимости между тестами.Такие хуки помогают управлять состоянием тестируемых объектов и делают тесты изолированными, что важно для надёжности и предсказуемости тестирования.
it и describeДля повторного использования одного и того же теста с разными
параметрами можно использовать цикл внутри блока describe
или it. Это позволяет уменьшить количество дублирующегося
кода и повысить покрытие тестами.
Пример:
const тестыСложения = [
{ a: 1, b: 2, expected: 3 },
{ a: -1, b: 2, expected: 1 },
{ a: -1, b: -1, expected: -2 }
];
describe('Тестирование калькулятора: Сложение', function() {
тестыСложения.forEach(function(тест) {
it(`должно складывать ${тест.a} и ${тест.b}`, function() {
const result = калькулятор.сложить(тест.a, тест.b);
assert.equal(result, тест.expected);
});
});
});
В этом примере один и тот же тест выполняется для разных наборов входных данных. Это уменьшает количество повторяющегося кода и делает тесты более компактными.
Mocha поддерживает асинхронное тестирование. В случае, если тест требует выполнения асинхронной операции, необходимо использовать функции обратного вызова или промисы. Mocha предоставляет несколько способов работы с асинхронностью:
it или beforeEach,
afterEach.Пример:
describe('Тестирование асинхронной операции', function() {
it('должно корректно обрабатывать данные', function(done) {
получитьДанные().then(function(данные) {
assert.equal(данные.length, 3);
done();
});
});
it('должно корректно обрабатывать данные с промисом', function() {
return получитьДанные().then(function(данные) {
assert.equal(данные.length, 3);
});
});
it('должно работать с async/await', async function() {
const данные = await получитьДанные();
assert.equal(данные.length, 3);
});
});
В этом примере показаны разные способы работы с асинхронными операциями: использование callback-функций, промисов и синтаксиса async/await.
Композиция тестовых наборов в Mocha позволяет создавать
организованные и легко читаемые тесты. Группировка тестов с помощью
describe, использование хуков для подготовки и очистки
данных, параметризация тестов и работа с асинхронностью — всё это даёт
возможность эффективно организовывать тестовые сценарии и снижать
дублирование кода. Это помогает не только улучшить структуру тестов, но
и повысить их гибкость и поддерживаемость в долгосрочной
перспективе.