Тестирование
Подготовка
Тестирование приложений Mithril.js достаточно простое. Самый простой способ начать - использовать ospec, mithril-query и JSDOM. Установить их довольно просто: откройте терминал и выполните следующую команду.
npm install --save-dev ospec mithril-query jsdom
Настройка также относительно проста и состоит из нескольких коротких шагов:
- Добавьте
"test": "ospec"
в секциюscripts
вашего файлаpackage.json
. В итоге это будет выглядеть примерно так, возможно, с другими полями, специфичными для вашего проекта:
{
"name": "my-project",
"scripts": {
"test": "ospec --require ./test-setup.js"
}
}
- Создайте файл настройки
test-setup.js
со следующим содержимым:
var o = require('ospec');
var jsdom = require('jsdom');
var dom = new jsdom.JSDOM('', {
// Чтобы получить доступ к `requestAnimationFrame`
pretendToBeVisual: true,
});
// Заполните глобальные переменные, необходимые Mithril.js для работы. Первые две также часто
// полезны непосредственно в тестах.
global.window = dom.window;
global.document = dom.window.document;
global.requestAnimationFrame = dom.window.requestAnimationFrame;
// Подключите Mithril.js, чтобы убедиться, что он загружается правильно.
require('mithril');
// И, наконец, убедитесь, что JSDOM закрывается после завершения тестов.
o.after(function () {
dom.window.close();
});
- Создайте компонент, например,
src/my-component.js
, со следующим кодом:
function MyComponent() {
return {
view: function (vnode) {
return m('div', vnode.attrs.text);
},
};
}
module.exports = MyComponent;
- И, наконец, создайте файл теста, например,
src/tests/my-component.js
, со следующим кодом:
var mq = require('mithril-query');
var o = require('ospec');
var MyComponent = require('../my-component.js');
o.spec('MyComponent', function () {
o('всё работает', function () {
var out = mq(MyComponent, { text: 'What a wonderful day to be alive!' });
out.should.contain('day');
});
});
После того, как вы все это настроили, в том же терминале, в котором вы устанавливали зависимости, выполните следующую команду.
npm test
Если все настроено правильно, вы должны увидеть вывод, который выглядит примерно так:
––––––
All 1 assertions passed in 0ms
Лучшие практики
Тестирование в большинстве случаев относительно простое. Каждый тест обычно состоит из трех частей: настройка начального состояния, выполнение кода и проверка результатов. Но есть несколько вещей, которые следует помнить при тестировании, чтобы получить максимальную пользу и сэкономить много времени.
Прежде всего, старайтесь писать тесты как можно раньше в процессе разработки. Не обязательно писать тесты немедленно, но желательно писать их по мере написания кода. Таким образом, если что-то работает не так, как вы ожидали, вы потратите 5 минут сейчас, точно зная, что происходит, вместо 5 дней подряд 6 месяцев спустя, когда вы пытаетесь выпустить эту замечательную идею приложения, которая теперь сломана. Не стоит застревать в этом болоте.
Тестируйте API, тестируйте поведение, но не тестируйте реализацию. Если вам нужно проверить, что при определенном действии генерируется событие, это вполне допустимо. Но не тестируйте всю структуру DOM в вашем тесте. Вы не хотите оказаться в ситуации, когда вам нужно переписывать часть пяти разных тестов только из-за того, что вы добавили простой класс, связанный со стилем. Вы также не хотите переписывать все свои тесты только потому, что вы добавили новый метод экземпляра к объекту.
Не бойтесь повторяться и абстрагируйтесь только тогда, когда вы буквально делаете одно и то же десятки-сотни раз в одном и том же файле или когда вы явно генерируете тесты. Обычно в коде хорошей идеей является абстрагирование повторяющейся логики в функцию, если она встречается более 2-3 раз, но при тестировании, даже если есть много повторяющейся логики, эта избыточность помогает вам получить контекст при отладке тестов. Помните: тесты - это описания, а не обычный код.
Модульное тестирование
Модульное тестирование изолирует части вашего приложения, обычно один модуль, но иногда даже одну функцию, и тестирует их как единый "юнит" (модуль). Оно проверяет, что при заданном конкретном вводе и начальном состоянии оно производит желаемый вывод и побочные эффекты. Это может показаться сложным, но это не так. Вот пара модульных тестов для оператора +
в JavaScript, примененного к числам:
o.spec('addition', function () {
o('works with integers', function () {
o(1 + 2).equals(3);
});
o('works with floats', function () {
// Да, это особенности представления чисел с плавающей точкой согласно стандарту IEEE-754.
o(0.1 + 0.2).equals(0.30000000000000004);
});
});
Точно так же, как вы можете модульно тестировать простые вещи, вы можете модульно тестировать и компоненты Mithril.js. Предположим, у вас есть этот компонент:
// MyComponent.js
var m = require('mithril');
function MyComponent() {
return {
view: function (vnode) {
return m('div', [
vnode.attrs.type === 'goodbye' ? 'Goodbye, world!' : 'Hello, world!',
]);
},
};
}
module.exports = MyComponent;
Вы можете легко создать несколько модульных тестов для этого.
var mq = require('mithril-query');
var MyComponent = require('./MyComponent');
o.spec('MyComponent', function () {
o("says 'Hello, world!' when `type` is `hello`", function () {
var out = mq(MyComponent, { type: 'hello' });
out.should.contain('Hello, world!');
});
o("says 'Goodbye, world!' when `type` is `goodbye`", function () {
var out = mq(MyComponent, { type: 'goodbye' });
out.should.contain('Goodbye, world!');
});
o("says 'Hello, world!' when no `type` is given", function () {
var out = mq(MyComponent);
out.should.contain('Hello, world!');
});
});
Как упоминалось ранее, тесты - это описания. Вы можете видеть из тестов, как компонент должен работать, и компонент делает это очень эффективно.