- Абстрактные знания
- Варианты оформления тестов
- Оформление файла
block.test.js
- Оформление файла
block.tests/testbundle.bemjson.js
- Оформление элемента
i-bem__test
- Проектные настройки
- Сборка и запуск тестов
- Демонстрация
Тест состоит из двух сущностей: тестовый бандл (раннер) и набор тестов.
Тестовые бандлы оформляются по полной аналогии с примерами, в папке block.tests
.
У каждого тестового бандла может быть свой дополнительный уровень переопределения.
Наборы тестов пишутся в технологии test.js
.
Набор тестов можно сделать для любой bem-сущности (блок, элемент и т.д.).
Для тестирования используется фреймворк mocha в режиме bdd
.
Для ассертов используется библиотека chai с плагином sinon-chai.
На момент запуска тестов метод chai.should
уже выполнен (http://chaijs.com/guide/styles/).
Для моков используется библиотека sinon.
Условно можно выделить два случая:
- Тесты, не требующие специфичного DOM-дерева, либо создающие его самостоятельно через js.
- Тесты, требующие специфичное DOM-дерево, созданное на этапе генерации страницы.
Для первого случая подходит простая схема оформления тестов:
common.blocks/block/
├── __elem
│ └── ...
├── block.css
├── block.deps.js
├── block.test.js
└── block.js
Тесты пишутся в файле block.test.js
.
В данном случае это тесты для блока, но можно точно также написать их для элемента или модификатора.
Этого достаточно, чтобы собрать дефолтный тестовый бандл, в рамках которого будут запущены тесты из этого файла.
Во втором случае нам требуется входное bem-дерево. Для этого по аналогии с примерами в папке блока создается директория
block.tests
:
common.blocks/block/
├── __elem
│ ├── block__elem.css
│ └── block__elem.title.txt
├── block.tests
│ ├── testbundle.bemjson.js
├── block.test.js
└── block.js
Здесь мы гораздо лучше контролируем процесс. В testbundle.bemjson.js
можно задать bem-дерево для полноценной страницы,
указать тесты каких конкретно блоков запускать.
Для этого конкретного бандла можно задать свой дополнительный уровень переопределения:
common.blocks/block/
├── __elem
│ ├── block__elem.css
│ └── block__elem.title.txt
├── block.tests
│ ├── testbundle.bemjson.js
│ └── testbundle.blocks
│ └── myblock
│ └── myblock.test.js
├── block.test.js
└── block.js
ВАЖНО! Файл testbundle.bemjson.js
должен интерпретироваться как блок в технологии bemjson.js
,
поэтому в имени тестового бандла нельзя использовать нижнее подчеркивание. Используйте -
для разделения
слов в названии.
Тесты пишутся под фреймворк mocha
с использованием библиотеки ассертов chai
.
Для запуска тестов используется модульная система.
Каждый тест декларируется под именем test
и провайдит undefined
.
Пример:
modules.define('test', function(provide) {
describe('block', function() {
it('Два умножить на два должно равняться четырем', function() {
(2*2).should.to.equal(4);
});
});
provide();
});
В testbundle.bemjson.js
пишется произвольный bemjson, плюс:
- Подключение
testbundle.test.js
(должно идти после подключения обычного js); - Нужно задекларировать блок
test
.
Пример:
({
block: 'page',
head: [
{ elem: 'css', url: '_testbundle.css', ie: false },
{ elem: 'js', url: '_testbundle.test.js' }
],
content: [
{ block: 'test' },
{ block: 'header' },
{ block: 'content' },
{ block: 'footer' }
]
})
test
это специальный блок, который поставляется с библиотекой bem-sets
. Он умеет запускать тесты.
Делает две простые вещи:
- Дает возможность прогнать тесты конкретных блоков;
- Подтягивает за собой тестовый фреймворк (mocha), библиотеку ассертов (chai) и пр.
Есть два способа оформления блока test
в testbundle.bemjson.js
.
Запустить все тесты, какие приехали по зависимостям:
{ block: 'test' }
Запустить тесты конкретных блоков:
{
block: 'test',
content: [
{ block: 'block' },
{ block: 'block', elem: 'elem' },
{ block: 'another-block'},
...
]
}
Если вам не подходит bemjson, который создаётся для дефолтного тестового бандла, вы можете заменить его,
создав свою технологию test-tmpl
. Для этого создайте модуль технологии .bem/techs/test-tmpl.js
, и из метода
getTemplate()
верните подходящий шаблон.
exports.baseTechPath = require.resolve('bem-sets/techs/test-tmpl.js');
exports.techMixin = {
getTemplate: function() {
return [
'({',
' block: "b-page",',
' head: [',
' { elem: "css", url: "_{{bemBundleName}}.css", ie: false },',
' { elem: "css", url: "_{{bemBundleName}}.css", ie: true }',
' ],',
' content: [',
' {',
' block: "test",',
' content: {{bemTmplContent}}',
' },',
' { block: "i-jquery", protocol: "http", mods: { version: "1.8.3" } },',
' { elem: "js", url: "_{{bemBundleName}}.test.js" }',
' ]',
'})'
];
}
};
В файле .bem/make.js
:
- Расширяем класс
TestNode
В файле .bem/levels/tests.js
:
- Указываем пути до технологий
test.js+browser.js+bemhtml
,test.js
,test-tmpl
,phantomjs
,browser.js
,vanilla.js
иbemhtml
.
Сначала нужно настроить сборку примеров (и убедиться, что она работает): https://github.com/bem/bem-sets/blob/master/docs/howto.ru.md
За сборку тестовых бандлов отвечает класс TestNode
(он расширяет класс ExampleNode
).
Расширяем этот класс:
- Указываем технологии, в которых будет собираться тестовый бандл;
- Указываем web-адрес, который смотрит на корень проекта (опционально);
- Указываем название репортера, который будет выводить результаты тестов в консоли (опционально).
MAKE.decl('TestNode', {
getTechs : function() {
return [
'bemjson.js',
'bemdecl.js',
'deps.js',
'bemhtml',
'test.js+browser.js+bemhtml',
'css',
'html',
'phantomjs'
];
},
webRoot: 'http://islands-page.dev/',
consoleReporter: 'teamcity'
})
Выше я предполагаю, что полный набор уровней уже указан для класса ExampleNode
.
webRoot
должен быть таким, чтобы от него можно было отложить путь до тестового бандла:
http://islands-page.dev/smth.sets/block.tests/test-bundle/test-bundle.html
.
webRoot
указывается со слешом на конце. По этому адресу должен отвечать веб-сервер.
Возможные значения поля consoleReporter
смотри в документации к mocha-phantomjs.
По умолчанию используется репортер spec
.
В файле .bem/levels/tests.js
должны быть указаны пути до технологий test.js+browser.js+bemhtml
, test.js
,
test-tmpl
, phantomjs
, browser.js
, vanilla.js
и bemhtml
, которые потребуются при сборке тестов.
var bemSets = require('bem-sets'),
PATH = require('path'),
PRJ_TECHS = PATH.resolve(__dirname, '../techs'),
PRJ_ROOT = PATH.resolve(__dirname, '../..');
exports.getTechs = function() {
return {
// Технологии для сборки и запуска тестов
'test.js+browser.js+bemhtml' : bemSets.resolve('./techs/test.js+browser.js+bemhtml.js'),
'test.js' : bemSets.resolve('./techs/test.js.js'),
'test-tmpl' : bemSets.resolve('./techs/test-tmpl.js'),
'phantomjs' : bemSets.resolve('./techs/phantomjs.js'),
'bemhtml' : PATH.join(PRJ_ROOT, 'bem-core/.bem/techs/bemhtml.js'),
'browser.js' : PATH.join(PRJ_ROOT, 'bem-core/.bem/techs/browser.js.js'),
'vanilla.js' : PATH.join(PRJ_ROOT, 'bem-core/.bem/techs/vanilla.js.js'),
// Технологии ниже указывать не обязательно, если вы расширяете
// набор технологий из BundleNode или ExampleNode, и они там уже заданы
'bemjson.js' : PATH.join(PRJ_TECHS, 'bemjson.js'),
'bemdecl.js' : 'bemdecl.js',
'deps.js' : 'deps.js',
'js' : 'js-i',
'css' : 'css',
'ie.css' : 'ie.css'
};
};
Дефолтный тестовый бандл для отдельной БЭМ-сущности:
$ bem make smth.tests/block.tests/default
$ bem make smth.tests/block__elem.tests/default
Рукотворный тестовый бандл:
$ bem make smth.tests/block.tests/testbundle
$ bem make smth.tests/block__elem.tests/testbundle
Все тестовые бандлы в рамках уровня smth.sets
:
$ bem make smth.sets/block.tests
Если в процесс сборки тестовых бандлов была добавлена технология phantomjs
, то в конце сборки тесты прогонятся
через phantomjs
, вы увидите результаты их выполнения прямо в консоли.
Собранный тестовый бандл можно открыть в браузере, там тоже будут показаны результаты выполнения тестов.
$ git clone git@github.com:bem/bem-core
$ cd bem-core
$ npm install
$ npm make libs
$ npm make sets