Модульное тестирование с помощью Mocha | OTUS
🔥 Начинаем BLACK FRIDAY!
Максимальная скидка -25% на всё. Успейте начать обучение по самой выгодной цене.
Выбрать курс

Курсы

Программирование
iOS Developer. Basic
-25%
Python Developer. Professional
-25%
Разработчик на Spring Framework
-25%
Golang Developer. Professional
-25%
Python Developer. Basic
-25%
iOS Developer. Professional
-25%
Node.js Developer
-25%
Unity Game Developer. Professional
-25%
React.js Developer
-25%
Android Developer. Professional
-25%
Software Architect
-25%
C++ Developer. Professional
-25%
Backend-разработчик на PHP Web-разработчик на Python Алгоритмы и структуры данных Framework Laravel PostgreSQL Team Lead Разработчик голосовых ассистентов и чат-ботов Архитектура и шаблоны проектирования Agile Project Manager Нереляционные базы данных Супер - интенсив по паттернам проектирования Супер-практикум по использованию и настройке GIT IoT-разработчик Подготовка к сертификации Oracle Java Programmer (OCAJP) Супер-интенсив «СУБД в высоконагруженных системах» Супер-интенсив "Azure для разработчиков"
Инфраструктура
Мониторинг и логирование: Zabbix, Prometheus, ELK
-25%
DevOps практики и инструменты
-25%
Архитектор сетей
-25%
Инфраструктурная платформа на основе Kubernetes
-25%
Супер-интенсив «ELK»
-16%
Супер-интенсив «IaC Ansible»
-16%
Administrator Linux. Professional MS SQL Server Developer Безопасность Linux PostgreSQL Reverse-Engineering. Professional CI/CD VOIP инженер Супер-практикум по работе с протоколом BGP Супер - интенсив по паттернам проектирования Супер - интенсив по Kubernetes Administrator Linux.Basic Супер-интенсив "Tarantool"
Специализации Курсы в разработке Подготовительные курсы
+7 499 938-92-02

Модульное тестирование с помощью Mocha

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

Несколько слов о тестируемом приложении

Для примера возьмём React-приложение Calculator. Оно имеет два юнит-компонента: keypad и display. Это точно юниты, не зависящие от других юнитов. Кроме того, компоненты разделены на презентационные (уже упомянутые display и keypad) и компоненты-контейнеры — calculator-app — единственный компонент, имеющий state, и определяющий, что отображается на экране при нажатии на кнопку.

Но вышеописанный компонент отвечает только за логику отображения, а что насчёт вычислений? Ими занимается отдельный модуль calculator, не имеющий React-зависимостей. И такой модуль прекрасно подходит для юнит-тестирования, т. к. не содержит I/O- и UI-зависимостей.

Что касается отделения логики калькулятора от компонента React, то это было сделано путём выделения логики в модуль calculator. Это простейший модуль, принимающий состояние калькулятора (объект), а также символ (цифру либо оператор). И, разумеется, возвращающий новое состояние калькулятора. Но если каждое состояние зависит от предыдущего, как получить самое первое состояние? Довольно просто — модуль экспортирует initialState, которое вы применяете для инициализации. То есть состояние калькулятора не является неизвестным, а включает в себя поле display, которое и надо показать приложению калькулятора для данного состояния.

Вот, например, начало кода:

module.exports.initialState = { display: '0', initial: true }

module.exports.nextState = (calculatorState, character) => {
  if (isDigit(character)) {
    return addDigit(calculatorState, character)
  } else if (isOperator(character)) {
    return addOperator(calculatorState, character)
  } else if (isEqualSign(character)) {
    return compute(calculatorState)
  } else {
    return calculatorState
  }
}

//....

Здесь не так важна специфика алгоритма, как простота функции, которую экспортирует наш модуль, ведь, получив состояние, мы можем всегда проверить следующее.

Приступим к тестированию

По большему счёту, все тестирующие фреймворки похожи: вы пишете тестовый код в функциях, а фреймворк их запускает. Причём конкретный код, выполняющий запуск, как правило, называют «runner».

Что касается Mocha, то здесь «Runner» представляет собой скрипт под названием mocha. Его можно легко увидеть, посмотрев на package.json в тестовом скрипте:

"scripts": {
...
    "test": "mocha 'test/**/test-*.js' && eslint test lib",
...
},

Это обеспечит запуск всех тестов в тестовой папке, названия которых начинаются с префикса test-. При запуске вы увидите приблизительно такой результат:

1_ZCXpZVRMgzZsCnaQMRZO4Q_1-20219-eeb47f.png

Понятное дело, что если тест не пройден, он помечается красным, и его надо будет исправить. Посмотрите на следующий код:

const {describe, it} = require('mocha')
const {expect} = require('chai')
const calculator = require('../../lib/calculator')

describe('calculator', function () {
  const stream = (characters, calculatorState = calculator.initialState) =>
    !characters
      ? calculatorState
      : stream(characters.slice(1),
               calculator.nextState(calculatorState, characters[0]))

  it('should show initial display correctly', () => {
    expect(calculator.initialState.display).to.equal('0')
  })
  it('should replace 0 in initialState', () => {
    expect(stream('4').display).to.equal('4')
  })
//...

Давайте первым делом импортируем mocha и библиотеку для проверок (assert’ов) expect. И выполним импорт нужных нам функций: describe, it, except. Далее выполним импорт тестируемого модуля — calculator.

Потом пойдут тесты, описанные с помощью функции it, допустим:

it('should show initial display correctly', () => {
    expect(calculator.initialState.display).to.equal('0')
})

Функция принимает строку, которая описывает тест, и функцию, которая и является непосредственно самим тестом. Однако it-тесты не могут быть «голыми», а должны быть в тестовых группах, определяемых посредством функции describe.

Что же находится в тестовой функции? На самом деле, всё, что мы пожелаем. В нашем случае мы проверяем, что исходное состояние display равняется нулю. Но как мы это выполняем? Ведь мы могли бы сделать что-то типа этого:

if (calculator.initialState.display !== '0')
  throw 'failed'

И такое решение бы подошло. Тест в Mocha не срабатывает, когда генерирует исключение, и это довольно просто. Однако expect делает тест намного приятнее, ведь в функции есть много фич, которые облегчают тестирование данных — к примеру, можно проверить, что массив либо объект равны конкретному значению.

В этом и заключается суть модульного тестирования: — запуск функции либо набора функций (или создание экземпляра объекта с последующим вызовом некоторых его методов, если мы говорим об ООП); — сравнение фактического результата и ожидаемого результата.

Источник: "Testing Your Frontend Code: Part II (Unit Testing)".

Не пропустите новые полезные статьи!

Спасибо за подписку!

Мы отправили вам письмо для подтверждения вашего email.
С уважением, OTUS!

Автор
0 комментариев
Для комментирования необходимо авторизоваться
🎁 Максимальная скидка!
Черная пятница уже в OTUS! Скидка -25% на всё!