РСС

Ношу шлем, тяжело дышу…

Меня зовут Антон Шувалов. Я работаю в Lazada. Кроме программирования я пишу музыку и иногда занимаюсь дизайном интерфейсов. Я есть в Twitter, Facebook, и на GitHub. Вы можете написать мне email.

Если вы задумали порадовать меня небольшим подарком (не может быть!) — вот список моих мещанских мечт.

Анализ покрытия JavaScript-кода тестами

Build Status Code Climate Coverage Status

Я попробую совсем коротко рассказать о том, как измерять покрытие NodeJS-проектов на GitHub с бейджами и тревисом. В принципе, это применимо и к модулям для браузера, ведь ничего не мешает тестировать их под NodeJS с JSDom.

И сразу дисклеймер — утилит для инструментирования и тестирования, ровно как и облачных сервисов очень много. Я использую mocha для тестов, jscoverage для инструментирования и Coveralls прикрученный к Travis как CI-сервис для анализа покрытия. Просто потому что я так привык.

Зачем знать процент покрытия тестами?

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

Как и любая объективная метрика — процент покрития влияет на качество. Просто потому что это наглядно, понятно, ну и из-за классных зёленых бейджей — они-то уж точно всё делают лучше!

Без анализа покрытия, надежность тестов очень размыта. Хотя, не стоит считать это серебрянной пулей — программы для анализа тоже могут ошибаться.

Инструментирование и анализ кода

javascript coverage

Если файл один…

Инструментируем модуль:

cd my-project
jscoverage index.js index-cov.js

Затем при тестировании покрытия нужно подключить специально подготовленную cov-версию эту версию вместо настоящей библиотеки. Для этого логичнее всего использовать переменную окружения. Советуют называть эту переменную MYPROJECT_COV. Некоторые библиотеки используют просто COV, но у меня возникли конфликты где-то в jscoverage, так что лучше добавлять префиксом название проекта.

/* test/index.js */
var myProject = process.env.MYPROJECT_COV
  ? require('../index-cov')
  : require('../index');

Теперь остается запустить тесты и сгенерировать отчет о покрытии. Делается это так:

MYPROJECT_COV=1 ./node_modules/.bin/mocha -R html-cov > coverage.html

Файлы coverage.html и index-cov.js стоит добавить в .gitignore, чтобы не закоммитить случайно.

Если файлов много…

Если в проекте много JS-файлов, которые скрываются за index.js, то обычно все эти штуки убираются в lib/, который инструментируется в lib-cov/:

cd my-project
jscoverage lib lib-cov

В index.js остается только код, который, в зависимости от переменной окружения подключает lib/ или lib-cov/:

/* index.js */
module.exports = process.env.MYPROJECT_COV
  ? require('../lib-cov')
  : require('../lib');

Ну и в tests/ проверять переменную окружения уже не нужно — так что там не остается ничего необычного. Не забудте добавить lib-cov/ в .gitignore.

Coveralls

Окей, Google. Теперь мы знаем насколько наш модуль покрыт тестами — можно смотреть в coverage.html, улучшать покрытие тестами, и всячески делать этот мир лучше.

Но вот беда — coverage.html есть только локально, да и при каждой генерации отчета о покрытии он перезаписывается, не оставляя никакой истории, и, соответственно, возможности наблюдать прогресс. Если вы разрабатываете небольшой модуль — наверное, в этом нет ничего страшного. Но если вы пишете что-то посложнее, то, скорее всего, вам хотелось бы знать, какое покрытие кода в разных бранчах, пулл-реквестах, иметь возможность заглянуть в историю. А как насчет клёвого бейджа — Coverage Status в readme.md?

Насколько я знаю, таких сервисов не мало. К примеру, code climate может следить за покрытием кода. Я же пока остановился (хотя, конечно, я только начал :D) на Coveralls. Coveralls интегрируется с Travis CI. В .travis нужно будет добавить несколько скриптов, которые после завершения обычного тестирования будут запустят тесты на покрытие и отправят результаты на сервер Coveralls.

after_success:
  - ./node_modules/.bin/jscoverage lib lib-cov
  - MYPROJECT_COV=1 ./node_modules/.bin/mocha test -R mocha-lcov-reporter | ./node_modules/coveralls/bin/coveralls.js

package.json

Для работы Coveralls понадобится парочка модулей:

Кстати, ничего не мешает вынести вынести генерацию coverage.html в package.json — не писать же руками каждый раз:

// package.json
"scripts": {
  "test": "mocha",
  "test-cov": "jscoverage lib lib-cov; MS_COV=1 ./node_modules/.bin/mocha -R html-cov > coverage.html",
  // ...
}

Теперь можно просто писать npm run test-cov и не вспоминать нужные команды каждый раз. Осталось только бейдж из coverals в readme.md добавить.

Примеры

В примерах можно посмотреть .travis.yml, package.json и покликать на бейджи:

Вместе с нашими друзьями: Mocha, JSCoverage, Coveralls и Travis

фото: Cyril Bosselut

Подписывайтесь на РСС. Всем добра и штурмовиков.

«Как рушатся комплексные системы», Ричард И. Кук
О фундаментальных проблемах больших запутанных систем
7 паттернов для рефакторинга JavaScript-приложений
Перевод отличной серии статей о проектировании и рефакторинге проектов
Музыка для работы
Мои плейлисты: теплый glitch, нежные девичьи голоса, интересная электроника и chillwave
Ссылколог
Коллекционирую полезные ссылки