Сервис для
сео - оптимизаторов

Найди ошибки на сайте
Ошибки мешают продвижению сайта
Исправь ошибки на сайте
Сайт без ошибок продвигать легче
Получи новых клиентов
Новые клиенты принесут больше прибыль

Модульное тестирование и TDD в Node.js - Часть 1

  1. Установка мокко и чай
  2. Ваш первый тест
  3. Заглушки с Синоном
  4. Шпионы с Синоном
  5. Заключение

Тестирование является важной практикой в ​​разработке программного обеспечения для улучшения качества программного обеспечения. Есть много форм тестирования; ручное тестирование, приемочные испытания, модульное тестирование и некоторые другие. В этом посте мы рассмотрим модульное тестирование в Node с использованием кофе мокко тестовые рамки. Модульные тесты обычно составляют большинство тестовых пакетов. Они тестируют небольшие блоки кода, как правило, метод или функцию, изолированно . Главное, что нужно помнить, это аспект изоляции .

В этой статье мы начнем с написания модульных тестов для функции, которая просто принимает некоторые данные, возвращает некоторые результаты и не имеет никаких зависимостей. Затем мы рассмотрим два типа тестовых двойников, заглушек и шпионов, используя библиотеку Sinon. Наконец, мы рассмотрим, как тестировать асинхронный код в Mocha. Давайте начнем!

Установка мокко и чай

Чтобы установить Mocha, просто запустите:

npm установить mocha -g

В отличие от других сред тестирования JavaScript, таких как Jasmine и QUnit, Mocha не имеет библиотеки утверждений. Вместо этого Мокко позволяет вам выбирать свой собственный. Популярные библиотеки утверждений, используемые с Mocha, включают should.js , expect.js , Chai и Node встроенный модуль assert. В этом посте мы собираемся использовать Чай.

Сначала давайте создадим файл package.json и установим Chai:

touch package.json echo {}> package.json npm install chai --save-dev

Чай имеет три разных вкуса. У него есть стиль must, ожидаемый стиль и стиль assert. Все они выполняют свою работу, и выбор одного из них - это просто вопрос того, как вы хотите, чтобы язык ваших тестов читался. Лично мне нравится стиль ожидания, поэтому мы будем его использовать.

Ваш первый тест

( Исходный код для проекта )

В нашем первом примере мы будем использовать разработку через тестирование (TDD) для создания функции конструктора CartSummary, которая будет использоваться для суммирования товаров, помещенных в корзину. Короче говоря, TDD - это практика написания тестов перед реализацией для управления дизайном вашего кода. TDD практикуется в следующих шагах:

  1. Написать тест и посмотреть, как он провалится
  2. Напишите минимальное количество кода, чтобы пройти этот тест
  3. Повторение

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

// tests / part1 / cart-summary-test.js var chai = require ('chai'); varpect = chai.expect; // мы используем стиль ожидаемого в Chai var CartSummary = require ('./../../ src / part1 / cart-summary'); description ('CartSummary', function () {it ('getSubtotal () должен возвращать 0, если элементы не переданы в', function () {var cartSummary = new CartSummary ([]); ожидаемо (cartSummary.getSubtotal ()). to.equal (0);});});

Функция description используется для настройки группы тестов с именем. Я имею тенденцию выставлять модуль в качестве имени, в данном случае CartSummary. Тест написан с использованием функции it. Функция it получает описание в качестве первого аргумента того, что должен делать тестируемый модуль. Второй аргумент функции it - это функция, которая будет содержать одно или несколько утверждений (также называемых ожиданиями) с использованием Chai в этом примере. Наш первый тест просто проверяет, что промежуточный итог равен 0, если в корзине нет товаров.

Чтобы запустить этот тест, запустите mocha tests --recursive --watch из корня проекта. Флаг рекурсии найдет все файлы в подкаталогах, а флаг наблюдения будет наблюдать все ваши исходные и тестовые файлы и перезапускать тесты при их изменении. Вы должны увидеть что-то вроде этого:

Вы должны увидеть что-то вроде этого:

Наш тест не пройден, потому что мы еще не реализовали CartSummary. Давайте сделаем это.

// src / part1 / cart-summary.js function CartSummary () {} CartSummary.prototype.getSubtotal = function () {return 0; }; module.exports = CartSummary;

Здесь мы написали минимальное количество кода, чтобы пройти наш тест.

Здесь мы написали минимальное количество кода, чтобы пройти наш тест

Давайте перейдем к нашему следующему тесту.

it ('getSubtotal () должен возвращать сумму цены * количество для всех элементов'), function () {var cartSummary = new CartSummary ([{id: 1, количество: 4, цена: 50}, {id: 2, количество: 2, цена: 30}, {id: 3, количество: 1, цена: 40}]); ожидайте (cartSummary.getSubtotal ()). to.equal (300);});

Неудачный вывод показывает, какое значение getSubtotal вернул красным и какое значение мы ожидали зеленым. Давайте пересмотрим getSubtotal, чтобы наш тест прошел.

// src / part1 / cart-summary.js function CartSummary (items) {this._items = items; } CartSummary.prototype.getSubtotal = function () {if (this._items.length) {вернуть this._items.reduce (function (subtotal, item) {вернуть subtotal + = (item.quantity * item.price);}, 0); } return 0; };

Наш тест проходит! Мы успешно использовали TDD для реализации метода getSubtotal.

Заглушки с Синоном

Допустим, теперь мы хотим добавить расчет налога в CartSummary в методе getTax (). Конечное использование будет выглядеть так:

var cartSummary = new CartSummary ([/ * ... * /]); cartSummary.getTax ('NY', function () {// выполняется после завершения запроса налогового API});

Метод getTax будет использовать другой модуль, который мы создадим, называемый налогом, с методом расчета, который будет заниматься сложностями расчета налога по штатам. Несмотря на то, что мы не внедрили налог, мы все равно можем завершить наш метод getTax, пока мы идентифицируем контракт для налогового модуля. Этот контакт сообщит, что должен существовать модуль под названием tax с методом вычисления, который принимает три аргумента: промежуточный итог, состояние и функцию обратного вызова, которая будет выполняться после завершения запроса API к налогу.

Как упоминалось ранее, модульные тесты тестируют блоки в изоляции. Мы хотим протестировать наш метод getTax, изолированный от tax.calculate. Пока tax.calculate придерживается своего контракта кода или интерфейса, getTax должен работать. Что мы можем сделать, так это подделать tax.calculate при тестировании getTax с использованием заглушки, типа двойного теста, который действует как контролируемая замена. Тестовые удвоения часто сравнивают с двойниками каскадеров, поскольку они заменяют один объект другим для целей тестирования, подобно тому, как актеры и актрисы заменяются двойниками каскадеров для опасных сцен действия. Мы можем создать эту заглушку с помощью библиотеки Sinon.

Чтобы установить Sinon, запустите:

npm установить sinon --save-dev

Первое, что нам нужно сделать, прежде чем мы сможем заглушить метод tax.calculate, это определить его. Мы не должны реализовывать его детали, но метод расчета должен существовать на объекте налога.

// src / part1 / tax.js module.exports = {Рассчитать: функция (промежуточный итог, состояние, выполнено) {// реализовано позже или параллельно нашим коллегой}};

Теперь, когда tax.calculate создан, мы можем заглушить его с помощью нашей предварительно запрограммированной замены с помощью Sinon:

// tests / part1 / cart-summary-test.js // ... var sinon = require ('sinon'); var tax = require ('./../../ src / part1 / tax'); description ('getTax ()', function () {beforeEach (function () {sinon.stub (налог, «рассчитать», функция (промежуточный итог, состояние, выполнено) {setTimeout (function () {done ({количество: 30} );}, 0);});}); afterEach (function () {tax.calculate.restore ();}); это ('get Tax () должен выполнить функцию обратного вызова с суммой налога', function ( готово) {var cartSummary = new CartSummary ([{id: 1, количество: 4, цена: 50}, {id: 2, количество: 2, цена: 30}, {id: 3, количество: 1, цена: 40 }]); cartSummary.getTax ('NY', функция (taxAmount) {ожидание (taxAmount) .to.equal (30); done ();});});});

Мы начинаем с требования Sinon и нашего налогового модуля в тест. Чтобы заглушить метод в Sinon, мы вызываем функцию sinon.stub и передаем ему объект с заглушаемым методом, имя метода, который нужно заглушить, и функцию, которая заменит оригинал во время нашего теста.

var stub = sinon.stub (объект, метод, func);

В этом примере я просто заглушил tax.calculate со следующим:

function (промежуточный итог, состояние, выполнено) {setTimeout (function () {done ({amount: 30});}, 0); }

Это просто функция, вызовы которой выполняются со статическим объектом налоговых сведений, содержащим сумму налога 30. setTimeout используется для имитации асинхронного поведения этого метода, поскольку в действительности он будет выполнять асинхронный вызов API для некоторой налоговой службы. Это происходит в блоке beforeEach, который выполняется перед каждым тестом. После каждого теста выполняется блок afterEach, который восстанавливает исходный tax.calculate.

Этот тест проверяет, что функция обратного вызова, переданная в getTax, выполняется с суммой налога, а не со всем объектом сведений о налогах, который передается в функцию обратного вызова для tax.calculate. Как видите, наш тест для getTax проходит, хотя мы еще не реализовали tax.calculate. Мы просто определили интерфейс этого. Пока tax.calculate поддерживает этот интерфейс, оба модуля должны работать правильно вместе.

Этот пример также демонстрирует асинхронное тестирование. Указав параметр в функции it (в этом примере вызывается done), Mocha передаст функцию и дождется ее выполнения перед завершением теста. Тест остановится и произойдет ошибка, если не выполнено в течение 2000 миллисекунд. Если бы мы не сделали это асинхронным тестом, тест завершился бы до того, как наши ожидания оправдались, что заставило бы нас думать, что все наши тесты проходят, а на самом деле это не так.

Теперь давайте напишем реализацию getTax для прохождения нашего теста:

CartSummary.prototype.getTax = function (state, done) {tax.calculate (this.getSubtotal (), state, function (taxInfo) {done (taxInfo.amount);}); };

Шпионы с Синоном

Одна из проблем нашего метода getTax заключается в том, что наш тест не проверяет, что tax.calculate вызывается с правильными промежуточными итогами и состоянием. Наш тест все равно прошел бы, если бы мы жестко закодировали значения промежуточных итогов и состояний в реализации getTax. Давай и попробуй в образец кода , Это не хорошо! Чтобы проверить, что tax.calculate вызывается с правильными аргументами, мы можем использовать шпионов Синона.

Шпион - это еще один тип двойного теста, который записывает, как используется функция. Сюда входит информация, например, с какими аргументами вызывается шпион, сколько раз вызывается шпион, и если шпион выдает ошибку. Самое замечательное в заглушках Синона состоит в том, что они построены поверх шпионов! Вот наш обновленный тест:

it ('getTax () должен выполнить функцию обратного вызова с суммой налога'), функция (выполнено) {var cartSummary = new CartSummary ([{id: 1, количество: 4, цена: 50}, {id: 2, количество: 2, цена: 30}, {id: 3, количество: 1, цена: 40}]); cartSummary.getTax ('NY', функция (taxAmount) {ожидание (taxAmount) .to.equal (30); ожидание ( tax.calculate.getCall (0) .args [0]). to.equal (300); ожидаемо (tax.calculate.getCall (0) .args [1]). to.equal ('NY'); ​​сделано ( );});});

Еще два ожидания были добавлены к этому тесту. getCall используется для получения первого вызова заглушки для tax.calculate. args содержит аргументы для этого вызова. Мы просто проверяем, что tax.calculate был вызван с правильной промежуточной суммой и состоянием в противоположность жестко закодированным значениям.

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

Заключение

В этом посте мы рассмотрели несколько практических примеров модульного тестирования в Node с использованием инфраструктуры тестирования Mocha, библиотеки утверждений Chai и Sinon для двойников теста в форме заглушки и шпионажа. Я надеюсь, вам понравился этот пост. Если у вас есть какие-либо вопросы, задайте их ниже или свяжитесь со мной в Twitter @ skaterdav85 ,

Часть 2 будет посвящена тестированию HTTP-запросов с помощью Nock.

Исходный код

Похожие

Ваш телефон прослушивает, и это не паранойя
... статья была обновлена ​​13 июня, чтобы пояснить, что такие приложения, как Facebook, не имеют автоматического доступа к вашим данным. Пару лет назад произошло нечто странное. Мы с другом сидели в баре, айфоны в карманах, обсуждали наши недавние поездки в Японию и то, как мы хотели бы вернуться. Уже на следующий день мы оба получили всплывающую рекламу в Facebook о дешевых обратных рейсах в Токио. Казалось, просто жуткое совпадение, но потом
Самый быстрый способ перенести фотографии и видео с вашего iPhone на ваш Mac
... вашем iPhone, вам нужно знать об утилите OS X под названием Image Capture. С его помощью вы можете перемещать фотографии и видео с телефона без необходимости использовать iPhoto или iTunes. В отличие от этих двух раздутых приложений, захват изображений загружается быстро и очень прост. Для начала подключите iPhone к компьютеру Mac, а затем запустите захват изображений. Приложение должно распознать ваш телефон и показать вам список ваших фотографий и видео. Чтобы увидеть больше фотографий
Как сделать игру похожей на переключатель цвета с помощью SpriteKit и Swift
... первый SKShapeNode Хорошей отправной точкой является создание узла для желтой секции в правом нижнем углу круга. Вы сделаете это, нарисовав контур формы. Рисование пути В GameScene.swift
Разработка гаджета для боковой панели Windows. Часть 1. Основы
[Платформа / боковая панель гаджетов Windows доступна для использования в следующих версиях Windows: Windows 7, Windows Vista и Windows Server 2008. Она может быть изменена или недоступна в последующих версиях. ] Первый из трех обзоров, в которых описано, как создать базовый гаджет для боковой панели Windows. В этом обзоре мы демонстрируем простой гаджет «Hello World» и шаги, необходимые для его установки и отображения на боковой панели. Вступление Гаджеты - это
Как загрузить тестирование и настроить производительность на вашем API
... ие несколько лет роль API значительно изменилась. Не так давно веб-API в основном использовались в качестве простых точек интеграции между внутренними системами. Это больше не правда. В настоящее время API-интерфейсы часто являются основной системой компании, одна из которых состоит из нескольких клиентских веб-приложений и мобильных приложений. Когда API использовались только для задач бэк-офиса, таких как извлечение отчетов, их производительность никогда не была ключевым фактором.
Создание веб-сервисов с помощью PHP и SOAP, часть 1
... способность разрабатывать программное обеспечение и сервисы для широкого спектра платформ является необходимым навыком, но не все используют один и тот же язык или платформу, и написание кода для их поддержки неосуществимо. Если бы существовал стандарт, который позволял нам писать код один раз и позволял другим легко взаимодействовать с ним из своего программного обеспечения. Ну, к счастью, есть ... и его зовут SOAP. (Раньше SOAP был аббревиатурой, обозначающей Simple Object Access Protocol,
Как установить веб-сервер Windows на свой компьютер с XAMPP
... вашего собственного веб-сервера"> Некоторые из наших статей здесь на MakeUseOf требуют использования вашего собственного веб-сервера. Хотя самый простой способ найти веб-пространство - это купить хостинг Разъяснение различных форм хостинга веб-сайтов [Объяснение технологии]
Тест MSI Trident 3 - мощный компьютер с размерами консоли
На рынке представлен целый ряд готовых компьютерных комплектов. Одной из компаний, которая активно продвигает этот тип решения, является тайваньский производитель MSI. В его распоряжении как минимум несколько таких компьютеров. Сегодня я хотел бы представить вам немного ближе к MSI Trident 3 с видеокартой GeForce GTX 1060
Китайский смартфон за 600 злотых - Doogee Y6 Review
внешний вид На первый взгляд выглядит не очень - смартфон кажется большим, вялым, толстым . Нечего смотреть. Устройство выполнено полностью из пластика, без возможности легко извлечь аккумулятор. Спереди - большой 5,5-дюймовый дисплей производства SHARP . Это имеет значение? Я не знаю В любом случае, он светит очень ярко, цвета, как в IPS, очень яркие, хорошо отражают реальность. Кроме того, производитель использовал 2.5D стекло,
... ипсетом Apple A10 Fusion нет никаких сомнений в том, что новый #Apple iPhone 7 Plus (# iPhone7Plus)...
... ипсетом Apple A10 Fusion нет никаких сомнений в том, что новый #Apple iPhone 7 Plus (# iPhone7Plus) входит в число самых мощных на сегодняшний день устройств. Тем не менее, этот смартфон также может страдать от проблем с производительностью, включая медленную или медленную производительность на ранней или более поздней стадии. В ответ на соответствующий вопрос о том, почему iPhone 7 plus работает очень медленно, этот контент раскрывает все возможные причины, а также некоторые рекомендуемые
Поддержка веб-камеры в Linux
... стрибутивов Обновлено: 12 ноября 2008 г. Если вы пользуетесь Интернетом, есть большая вероятность, что вы используете какой-либо обмен мгновенными сообщениями, голосовую связь, видео - или и то, и другое - телефонию или другие средства связи, чтобы оставаться на связи с людьми во всем мире. Веб-камеры играют большую роль в интернет-общении. Они позволяют нам увидеть другую сторону, за тысячи километров. Определенно важная часть нашей веб-жизни. Веб-камеры могут

Комментарии

Антивирусная программа говорила что-то о подозрительной загрузке (то есть неправильно понимает файл патча как вредоносный, потому что часть его кода выглядит как кусок вируса)?
Антивирусная программа говорила что-то о подозрительной загрузке (то есть неправильно понимает файл патча как вредоносный, потому что часть его кода выглядит как кусок вируса)? Или он настроен на то, чтобы вообще ничего не говорить и просто удалять то, что он считает опасным, сам по себе (настройка, которая является бессмысленной чепухой)? Привет, Полимахос
Ваша машина не используется большую часть года?
Ваша машина не используется большую часть года? И поэтому вы должны нести стоимость полной политики ответственности. Вполне возможно, что это скоро изменится из-за временного изъятия легковых автомобилей и мотоциклов. Это не означает, однако, что вам не придется платить за OC. К сожалению, этот вариант может повлиять на дальнейшее повышение страховых цен для всех водителей. Временный вывод легкового автомобиля или мотоцикла был ликвидирован 20 лет назад - в 1997 году. С тех пор, независимо
Немногие генерируют большую часть трафика или оно распределено более равномерно?
Node как?
node как? SKShapeNode, пусть nodeB = contact.bodyB.node как? SKShapeNode {if nodeA.fillColor! = NodeB.fillColor {dieAndRestart ()}}}} Наконец, добавьте эту строку в конец didMove (для :) PhysicsWorld.contactDelegate = self Поскольку вы устанавливаете GameScene в качестве contactDelegate of PhysicsWorld, didBegin (_ :) будет вызываться всякий раз, когда узел игрока перекрывает один из участков препятствий. Строка if let проверяет, чтобы убедиться, что оба
1. Чем занимается ваш бизнес?
1. Чем занимается ваш бизнес? Чтобы создать лучший веб-сайт для вашего бизнеса, компании, занимающейся веб-дизайном, необходимо полностью понимать ваш бизнес. Они не могут создать сайт, который работает для вас, если они мало знают о вашей компании. Важно, чтобы вашей компании, занимающейся веб-дизайном, потребовалось время, чтобы познакомиться с вашим бизнесом. Они должны спросить об истории вашего бизнеса, предлагаемых вами продуктах или услугах, ваших сотрудниках, конкурентах
Как ускорить ваш iPhone 7 Plus?
Как ускорить ваш iPhone 7 Plus? Ниже перечислены некоторые рекомендуемые обходные пути и полезные советы, которые помогут ускорить работу вашего iPhone 7 Plus, который замедляется из-за низкого или недостаточного объема памяти или снижения производительности. Шаг 1. Управление внутренней памятью Это хорошая практика, чтобы держать в курсе, что использует большую часть внутренней памяти вашего iPhone. Таким образом, вы можете управлять своим устройством
Или, с другой стороны, Ищете сайт, который демонстрирует ваш бизнес в Интернете?
Или, с другой стороны, Ищете сайт, который демонстрирует ваш бизнес в Интернете? Тема SmartFix WordPress подходит для всех видов ремонта, таких как ремонт КПК, ремонт рабочей зоны, ремонт iPad, ремонт планшетов, ремонт принтеров, восстановление информации и ремонт развлекательных программ. SmartFix продвигает ваш бизнес в Интернете. Это чрезвычайно опытный, совершенный и фантастический план. Вы хотите провести капитальный ремонт своего сайта экспертным способом, который увеличит скорость

Это имеет значение?
Антивирусная программа говорила что-то о подозрительной загрузке (то есть неправильно понимает файл патча как вредоносный, потому что часть его кода выглядит как кусок вируса)?
Или он настроен на то, чтобы вообще ничего не говорить и просто удалять то, что он считает опасным, сам по себе (настройка, которая является бессмысленной чепухой)?
Ваша машина не используется большую часть года?
Node как?
Node как?
Node как?
1. Чем занимается ваш бизнес?
1. Чем занимается ваш бизнес?
Как ускорить ваш iPhone 7 Plus?