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

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

Интеграционное тестирование - это процесс тестирования программных модулей как группы. Это может означать использование такого инструмента, как Selenium, чтобы прочесать ваш сайт и убедиться, что все пользовательские функции работают должным образом (тесты взаимодействия с пользователем).

Модульное тестирование - это процесс тестирования логики отдельных программных модулей. Это может быть полезно, если вы хотите убедиться, что ваша функция проверки охватывает все крайние случаи, или даже если вам нужна обратная связь в процессе разработки (кто угодно TDD?).

В этой статье основное внимание будет уделено реализации интерфейсных модульных тестов. Наш «стек» будет состоять из 1) Karma в качестве средства выполнения теста и 2) Mocha в качестве среды тестирования. Мы также позаботимся о том, чтобы он хорошо работал с 3) RequireJS.

Карма

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

Сначала устанавливаем фреймворки:

npm install karma --save-dev
npm install karma-mocha --save-dev
npm install karma-chai --save-dev
npm install karma-requirejs --save-dev

Karma поставляется со встроенными плагинами для Mocha, Chai и RequireJS. Мы будем использовать Mocha для написания тестов, Chai для утверждений и RequireJS для загрузки модулей AMD. Позже мы рассмотрим их подробнее.

Затем установите плагины (и PhantomJS):

npm install karma-chrome-launcher --save-dev
npm install karma-firefox-launcher --save-dev
npm install karma-opera-launcher --save-dev
npm install karma-safari-launcher --save-dev
npm install karma-phantomjs-launcher --save-dev
npm install phantomjs --save-dev

Karma мощна тем, что позволяет запускать тесты одновременно в нескольких браузерах. Мы будем поддерживать Firefox, Opera, Chrome, Safari и PhantomJS. Эти плагины для браузера необходимы, чтобы помочь Karma найти соответствующие двоичные файлы, что означает, что вы можете запускать тесты только в браузерах, которые уже установлены на вашем локальном компьютере.

О, и пока вы это делаете, добавьте карму-покрытие

npm install karma-coverage --save-dev

Этот плагин является форком Istanbul, который даст нам возможность легко отслеживать покрытие кода.

Карма

Затем создайте файл конфигурации вашей кармы. Это можно сделать с помощью команды «karma init» или путем создания файла karma.conf.js в корневом каталоге вашего приложения. Вот как выглядит мой конфигурационный файл:

module.exports = function(config) {
  config.set({
    basePath: '',
    frameworks: ['mocha', 'requirejs', 'chai'],
    files: [
        {pattern: './config.js', included: true},
        {pattern: './app/**/*.json', included: false},
        {pattern: './app/**/*.html', included: false},
        {pattern: './app/**/*.js', included: false},
        {pattern: './library/**/*.js', included: false},
        {pattern: './unit-tests/**/*.js', included: false},
        {pattern: './unit-tests/main.js', included: true}
    ],
    exclude: [
        './app/private/header/failure.js'
    ],
    preprocessors: {
        './app/**/*.js': 'coverage'
    },
    coverageReporter: {
      type : 'text-summary',
      dir : 'coverage/',
      includeAllSources : true
    },
    reporters: ['progress', 'junit', 'coverage'],
    browsers: ['PhantomJS', 'Chrome', 'Firefox', 'Safari'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    singleRun: false,
    concurrency: Infinity,
  })
}

Важно понимать, что происходит в конфигурационном файле Karma:

basePath: '',
frameworks: ['mocha', 'requirejs', 'chai'],

basePath используется для разрешения всех относительных путей, определенных в свойствах конфигурации files и excludes.

files: [
    {pattern: 'config.js', included: true},
    {pattern: 'app/**/*.json', included: false},
    {pattern: 'app/**/*.html', included: false},
    {pattern: 'app/**/*.js', included: false},
    {pattern: 'libs/**/*.js', included: false},
    {pattern: 'unit-tests/**/*.js', included: false},
    {pattern: 'unit-tests/main.js', included: true}
],

файлы сообщает Karma, какие файлы следует обслуживать, при запуске веб-сервера. Сюда необходимо включить любые файлы, которые необходимо импортировать, протестировать или просмотреть в любом качестве. Шаблоны файлов используют библиотеку minimatch - т.е. app / ** / *. Js будет включать все файлы во всех подкаталогах каталога приложения. Установите included: true только для файлов, которые должны быть включены как тег ‹script›, иначе вы можете столкнуться с ошибками с RequireJS.

exclude: [
    './app/failure.js'
],

exclude позволяет указать файлы, которые Karma не должна показывать. Это полезно, когда вы хотите использовать Minimatch для включения всего каталога за вычетом нескольких исключительных файлов.

preprocessors: {
    './app/**/*.js': 'coverage'
},
coverageReporter: {
    type : 'text-summary',
    dir : 'coverage/',
    includeAllSources : true
},
reporters: ['progress', 'junit', 'coverage'],

Этот фрагмент конфигурации отвечает за отчетность и покрытие кода. Код, который необходимо проверить на покрытие, указывается в препроцессорах, а параметры покрытия можно изменить в extensionReporter. Затем желаемый формат вывода указывается в средствах отчетов (в этом случае "прогресс" отображает количество выполненных тестов, "junit" каналы результаты в файл xml, а «покрытие» регистрирует сводку результатов покрытия.

browsers: ['PhantomJS', 'Chrome', 'Firefox', 'Safari', 'Opera'],    
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
singleRun: true,
concurrency: Infinity,

В этом примере мы тестируем браузеры, включая PhantomJS, Chrome, Firefox, Safari и Opera. Karma будет запускать веб-сервер на порту 9876. Выходной журнал цвета включается с помощью logLevel из «информации». Сервер автоматически отслеживает (autoWatch: true) изменения файлов. Каждый запуск будет проверять все браузеры одновременно (concurrency: Infinity) и завершится закрытием всех браузеров / кармы (singleRun: true ).

RequireJS

Большая часть работы по настройке RequireJS уже проделана, если вы до сих пор следили за ней. Мы уже включили файл конфигурации RequireJS (см. Фрагмент ниже), и теперь Karma настроена на использование RequireJS в качестве фреймворка.

files: [
    {pattern: './config.js', included: true},
    {pattern: 'unit-tests/main.js', included: true}
]

Остается выполнить некоторую финальную настройку, которую мы сделаем в файле main.js.

var tests = [];
for (var file in window.__karma__.files) {
    if (/\_test\.js$/.test(file)) { tests.push(file); }
}
requirejs.config({
    baseUrl: '/base/app/',
    deps: tests,
    callback: mocha.run
});

Мы используем регулярное выражение и тот факт, что karma обслуживает все свои файлы в window .__ karma __. Files, чтобы указать все наши тестовые файлы (которые мы помечаем с помощью _test). Вызов mocha.run после обновления requirejs.config () инициализирует тестирование!

Если вы до сих пор следили за всем, вы готовы приступить к написанию модульных тестов - просто пометьте их «_test.js». После того, как вы написали несколько тестов, запустить их так же просто, как ввести «karma start karma.conf.js» в командной строке (вам может потребоваться указать путь, если вы не установили karma глобально - «/ node_modules / karma / bin / karma start karma.conf.js »).

Удачного тестирования!

Обновление (18.11.2017):

По запросу, вот что выглядит мое дерево каталогов после установки:

Это конкретное приложение построено на Backbone.js, поэтому у меня есть папки, разделенные по ролям (например, администратора) и коллекциям / моделям / представлениям. Неважно, куда вы поместите main.js, если вы укажете правильный путь в файле конфигурации Karma.

Вот как выглядит настоящий тест:

Это упрощенный тест базового представления. Мы используем хук mocha before () для создания экземпляра представления (AddIpDlgView.js), проверяем, является ли он подклассом базового представления, и проверяем действительность нескольких IP-адресов с помощью addIpDlgView.isValidIPv4 (). Зависимости импортируются с использованием типичного синтаксиса define ().

Как только вы начнете писать более сложные модульные тесты, вы сможете добавлять шпионов, заглушек и имитаций с помощью такой библиотеки, как Sinon.js.