Вот и я снова! ♬

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

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

Когда мы запускали этот проект, мы выбрали наиболее используемые на тот момент инструменты: Karma, PhantomJS, Mocha, Webpack и Isparta.

Мы пытались использовать JSDOM, но с React просто не получалось, и мы потратили много времени на создание нашей среды, и нам пришлось двигаться дальше.

Это было медленно, но я к этому привык, от одного изменения к другому на моей машине требовалось 3 секунды (ну, для TDD это очень медленно!), Но я спорил сам с собой, что мне пришлось запускать karma, phantomjs и затем транспилируем наш код с помощью webpack, и это требует времени… черт возьми!

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

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

Я нашел эту статью Томаза, и он говорил убрать из игры webpack, карму и фантом. (Чёрт ?!)

Я, конечно, проигнорировал его! хахахаха

Я потратил больше времени на поиски, а потом прочитал эту статью из Vitality, испытывая те же чувства. Он предложил скомпилировать webpack, создав хук с webpack-shell-plugin для вызова мокко после завершения компиляции.

Я пробовал, не получилось!

Так я дошел до статьи Оле Михельсена, в которой предлагался аналогичный подход от Vitality. На этот раз без веб-пакета.

Мокинг загрузчиков из веб-пакета с помощью require.extension:

const noop = () => {}; 
require.extensions[‘.css’] = noop; 
require.extensions[‘.ico’] = noop;
require.extensions[‘.png’] = noop; 
require.extensions[‘.svg’] = noop;

Почти готово, мой дорогой Ватсон!

Но жизнь непростая. Мы использовали псевдоним webpack, модули css и прочее. Нам нужно нечто большее !!

Подделка файлов .css нарушила бы тесты с использованием classNames. Как это решить?

mock-css-модули

Это здорово, потому что возвращается к исходному имени класса !!!

Вторая часть заключалась в решении проблем с псевдонимом webpack, поэтому я нашел этот замечательный пакет под названием babel-plugin-wepack-alias.

Но мы снова наткнулись на другую стену. Если вы используете inject-loader или proxyquire, это не сработает, потому что сопоставленный псевдоним из babel-plugin-webpack будет иметь другой путь, а proxyquire и inject-loader не сможет их найти. Так что же нам делать? Плакать! (Шучу!)

Эрик Ардал в своей статье предложил использовать sinon.stub для имитации модулей. У него есть свои недостатки.

// a.js
export function hello() {}
// BAD
// b.js
import {hello} from './a';
const greet = hello();
export function wolrd() {
 return greet;
}
// GOOD
// b.js
import {hello} from ‘./a’;
export function wolrd() {
 const greet = hello();
 return greet;
}

Мы могли бы попробовать пошутить, потому что он для вас издевается над всеми модулями, но мне это не пришло в голову.

Что насчет покрытия кода? Это было довольно просто. Просто добавьте в свой проект babel-plugin-istanbul » и nyc , и готово!

А теперь некоторые цифры всего нашего теста, работающего без режима просмотра:

PhantomJS, Karma и Webpack:
реальный 1m17.745s
пользовательский 1m19.767s
sys 0m7.583s

JSDOM, Mocha, Babel:
real 0m23.180s
user 0m17.785s
sys 0m1.800s

УРА, намного быстрее !!!

Итак, вот настройка нашего проекта:

// package.json
“test”: “./node_modules/.bin/_mocha”
“coverage”: "BABEL_ENV=test nyc ./node_modules/.bin/_mocha”
// test/mocha.opts
 — compilers js:babel-register
 — require jsdom-global/register
 — require test/setup.js
src/**/*.spec.js
// test/setup.js
var mockCssModules = require('mock-css-modules');
mockCssModules.register(['.sass', '.scss', '.css']);

const noop = () => {};

require.extensions['.ico'] = noop;
require.extensions['.png'] = noop;
require.extensions['.svg'] = noop;
require.extensions['.jpg'] = noop;
// .babelrc
{

  "env": {
    "test": {
      "presets": ["es2015", "stage-0", "react"],
      "plugins": [
        [ "babel-plugin-webpack-alias", { "config": "./test/webpack.config.test.js" } ],
        ["istanbul", {
          "exclude": [
            "**/*.spec.js"
          ],
          "useInlineSourceMaps": false
         }]
       ]
    }
  }
}
// test/webpack.config.test.js
var path = require('path');

var config = {
  resolve: {
    alias: {
      something: find('actions')
    }
  }
};

function find(alias) {
  return path.join(__dirname, '..', 'src', alias);
}

module.exports = config;

И это все!! Большое спасибо Томазу, Оле и Эрику, которые меня вдохновили!

Спасибо!

Изначально это было опубликовано в Блоге разработчиков Crave’s в 2017–01–13 годах.