Важное место при разработке на Node.js занимает тестирование. И в данном случае гораздо легче воспользоваться имеющимися фреймворками, которые упрощают процесс тестирования. Одним из таких фреймворков является Mocha. Подробнее о фреймворке можно узнать на официальной странице Mochajs. В данном же случае мы рассмотрим некоторые базовые стороны работы с ним.
Определим в папке проекта новый файл package.json со следующим содержимым:
{ "name": "testapp", "version": "1.0.0" }
Далее добавим в проект пакет mocha с помощью следующей команды:
npm install mocha --save-dev
Так как фреймворк Mocha необходим только для тестирования приложения, то он добавляется в файле package.json в секцию devDependencies
с помощью команды --save-dev
.
Для тестирования определим простейший модуль. Для этого добавим в проект файл operations.js со следующим содержимым:
module.exports.multiply = function(x,y){ return x * y; }
Здесь определена функция умножения двух чисел.
Для тестирования этого модуля добавим в проект новый файл operations.test.js:
const operations = require("./operations"); it("should multiply two numbers", function(){ const expectedResult = 15; const result = operations.multiply(3, 5); if(result!==expectedResult){ throw new Error(`Expected ${expectedResult}, but got ${result}`); } });
Рассмотрим этот тест. Для тестирования результата применяется функция it(), которая предоставляется фреймворком Mocha.
Эта функция принимает два параметра: текстовое описание тестируемого действия, по которому его можно идентифицировать, и саму тестирующую функцию.
К примеру, нам надо проверить работу выше определенной функции multiply()
, которая умножает два числа.
Для этого в эту функцию надо передать два числа и сравнить ее результат с ожидаемым. Если результат не совпадает с ожидаемым значением, то генерируется ошибка.
Для упрощения запуска тестов изменим файл package.json следующим образом:
{ "name": "testapp", "version": "1.0.0", "scripts":{ "test" : "mocha *.test.js" }, "devDependencies": { "mocha": "^10.2.0" } }
Здесь добавляется секция "scripts", в которой определяется команда "test". Эта команда выполняет команду "mocha *.test.js", которая запускает тестирование с помощью mocha, передавая фреймворку все файлы, которые оканчиваются на ".test.js"
Если у нас один файл теста, то мы могли бы сразу указать полное имя файла, типа mocha operations.test.js
Далее в командной строке перейдем к папке проекта и выполним команду npm test:
c:\app> npm test > testapp@1.0.0 test > mocha *.test.js ✔ should multiply two numbers 1 passing (5ms) c:\app>
В данном случае консоль указывает, что тест пройден.
Но, если мы изменим код теста:
const operations = require("./operations"); it("should multiply two numbers", function(){ const expectedResult = 16; const result = operations.multiply(3, 5); if(result!==expectedResult){ throw new Error(`Expected ${expectedResult}, but got ${result}`); } });
То тест не будет проходить, так как результат - 15 не равен ожидаемому результату - числу 16. И консоль уведомит об этом при повторном запуске теста:
c:\app> npm test > testapp@1.0.0 test > mocha *.test.js 1) should multiply two numbers 0 passing (6ms) 1 failing 1) should multiply two numbers: Error: Expected 16, but got 15 at Context.(operations.test.js:8:9) at process.processImmediate (node:internal/timers:478:21) c:\app>
Подобным образом мы можем определять и другие тесты. Например, изменим файл модуля operations.js:
module.exports.multiply = function(x,y){return x * y;} module.exports.add = function(x, y){ return x + y;}
Теперь в файле была добавлена функция для сложения чисел. Протестируем ее в operations.test.js:
const operations = require("./operations"); it("should multiply two numbers", function(){ const expectedResult = 15; const result = operations.multiply(3, 5); if(result!==expectedResult){ throw new Error(`Expected ${expectedResult}, but got ${result}`); } }); it("should add two numbers", function(){ const expectedResult = 16; const result = operations.add(9, 7); if(result!==expectedResult){ throw new Error(`Expected ${expectedResult}, but got ${result}`); } });
Запустим тест:
c:\app> npm test > testapp@1.0.0 test > mocha *.test.js ✔ should multiply two numbers ✔ should add two numbers 2 passing (5ms) c:\app>
Немного отличается тестирование асинхронных функций. Например, определим в модуле operations.js асинхронную функцию:
module.exports.multiply = function(x,y){return x * y;} module.exports.add = function(x, y){ return x + y;} module.exports.multiplyAsync = function (a, b, callback){ setTimeout(function(){ callback(a * b); }, 1000) }
Протестируем эту функцию в operations.test.js:
const operations = require("./operations"); it("should multiply two numbers", function(){ const expectedResult = 15; const result = operations.multiply(3, 5); if(result!==expectedResult){ throw new Error(`Expected ${expectedResult}, but got ${result}`); } }); it("should add two numbers", function(){ const expectedResult = 16; const result = operations.add(9, 7); if(result!==expectedResult){ throw new Error(`Expected ${expectedResult}, but got ${result}`); } }); it("shoud async multiply two numbers", function(done){ const expectedResult = 12; operations.multiplyAsync(4, 3, function(result){ if(result!==expectedResult){ throw new Error(`Expected ${expectedResult}, but got ${result}`); } done(); }); });
Особенностью тестирования асинхронных функций является то, что чтобы они завершились до завершения теста, в тестирующую функцию передается функция done()
.
Причем при окончании тестирования нам надо вызвать эту функцию. Тем самым через подобную функцию Mocha сможет контролировать выполнение теста.
c:\app> npm test > testapp@1.0.0 test > mocha *.test.js ✔ should multiply two numbers ✔ should add two numbers ✔ shoud async multiply two numbers (1002ms) 3 passing (1s) c:\app>
Если мы не передадим функцию done в тест, тогда тест завершится раньше, чем завершится асинхронная функция.