- PVSM.RU - https://www.pvsm.ru -
В этой статье я хочу представить вам новую библиотеку для тестирования AVA [1]. Относительно новую, ей уже больше 2-х лет, и она обзавелась солидным количеством плагинов и конечно же сообществом которое ее развивает. Мы посмотрим на функционал библиотеки. Настроим окружение и напишем пару тестов, чтобы посмотреть на библиотеку в действии.
В первую очередь библиотека предлагает скорость. Тесты запускаются параллельно, что дает ускорение выполнения тестов. В качестве примера приводится проект Pageres [2], в котором тестирование было перенесено на AVA [3], что дало увеличение почти в 3 раза(31 секунда было и 11 стало). Тесты не зависят от глобального состояния и от других тестов, что конечно же упрощает тестирование. Из коробки сразу идет использование es2015.
Установить соответствующий npm модуль. Установим как зависимость для работы в конкретной папке.
// package.json
...,
"scripts": {
"test": "ava"
},
...
npm install -D ava
npm test
или глобально
npm i -g ava
ava
Настало время написать первый тест, возьмем пример из официального репозитория. И сохранить его как my-tests.js
import test from 'ava';
test('foo', t => {
t.pass();
});
test('bar', async t => {
const bar = Promise.resolve('bar');
t.is(await bar, 'bar');
});
Сразу видим использование es2015 со стрелочными функциями, let и async. На мой взгляд, не обманули и действительно минималистичный синтаксис.
Запускаем тесты
npm test my-tests.js
// or
ava my-tests.js
И получаем результат
2 passed
Если мы хотим увидеть более подробную информацию о каждом тесте, мы можем использовать параметры для модуля
ava my-tests.js --verbose
// or
ava my-tests.js -v
foo
bar
2 tests passed
Так же мы можем запустить watcher, чтобы разрабатывать в стиле TDD
ava my-tests.js --watch
// or
ava my-tests.js -w
Поспотреть полный список параметров можно
ava --help
Простой тест:
test('description', t => {
});
Одна из самых распространенных ситуаций, когда нужно выполнить только один тест из всех:
test.only('test only', t => {
t.pass();
});
Пропуск теста, может понадобиться при рефакторинге, поиске ошибки:
test.only('test only', t => {
t.fail();
});
Вынесено на уровень API, что очень интересно. Можно сделать напоминалку прямо в тестах.
test.todo('описание');
Если нам нужно протестировать асинхронную часть кода, мы можем воспользоваться "cb":
test.cb('callback', t => {
setTimeout(function() {
console.log('time');
t.end();
}, 3000);
});
Параметр serial, позволит нам выполнять тесты в определенной последовательности. Например, мы хотим проверить существование конфигурационного файла. Если его нет, его нужно создать. Мы сделаем 2 теста, один будет создавать наш файл, а второй проверять.
И нам удобней будет, чтобы они запускались именно последовательно.
import test from 'ava';
import fs from 'fs';
const path = 'serial-test-one.txt';
test.cb('serial 1: create file', t => {
fs.writeFile(path, 'test', function(err) {
if (err) {
t.fail();
} else {
t.pass();
}
t.end();
});
});
test.cb('serial 2: is file exists', t => {
fs.access(path, fs.F_OK, function(err) {
if (err) {
t.fail();
} else {
t.pass();
}
t.end();
});
});
Написав такой код мы получаем
serial-one › serial 2
serial-one › serial 1
2 tests passed
И видим, что тесты запустились и закончились успешно. Но это не правильно, данных код не гарантирует выполнение в нужным нам порядке. Если мы сымитируем ситуацию когда файла еще нет, skip-ем тест создания, мы получим ошибку
- serial-one › serial 1
serial-one › serial 2 Test failed via t.fail()
1 test failed
1 test skipped
1. serial-one › serial 2
AssertionError: Test failed via t.fail()
serial-one.js:19:9
FSReqWrap.oncomplete (fs.js:123:15)
Чтобы гарантировать последовательность мы можем использовать параметр --serial или -s
ava serial-one.js -s
serial-one › serial 1
serial-one › serial 2
2 tests passed
Или использовать
test.cb.serial('serial 1', t => {
...
});
Тест падает и мы об этом знаем. Мы можем об этом явно указать.
test.failing('failing', t => {
t.fail();
});
В результате видим, что этот тест падает, но мы знаем об этом, и в идеале уже, что то делаем.
1 known failure
Очень приятно, что мы можем совмещать параметры. Это позволяет нам реализовать любой сложности тесты и запускать в только необходимые и в нужном порядке.
test.only.cb
test.cb.only
Для настройки окружения тестов есть before и after. Они будет выполнены один раз на старте выполнения тестов и в конце соответственно.
test.before(t => {
});
test.after(t => {
});
Так же мы можем объявить несколько таких функций и они будет вызываться в порядке добавления
test.before(t => {
console.log('before');
});
test.before(t => {
console.log('before#2');
});
before
before#2
Работает и для after.
Если текст падает, after не вызываются. Чтобы исправить ситуацию нужно использовать модификатор always.
test.after.always(t => {
});
Когда нам нужно настраивать окружение перед каждый тестом используем beforeEach и afterEach.
test.beforeEach(t => {
});
test.afterEach(t => {
});
Для них сохраняется поведение как и для before и after: порядок объявления и при ошибке в тесте after не вызываются(если нет always).
test('test', t => {
t.pass();
t.skip.fail();
t.truthy(true);
t.truthy('unicorn');
t.falsy(false);
t.falsy(1 === 0);
t.true(true);
t.false(false);
t.is(1, 1);
t.not(1, 0);
t.deepEqual([0, 1, 2], [0, 1, 2]);
t.notDeepEqual([0, 2, 2], [0, 1, 2]);
});
Очень удобный deepEqual, и возможность пропустить проверку.
Отдельно рассмотрим вывод ошибок, он очень детальный.
test(t => {
const a = /foo/;
const b = 'bar';
const c = 'baz';
t.true(a.test(b) || b === c);
});
t.true(a.test(b) || b === c)
| | | |
| "bar" "bar" "baz"
false
Что безусловно помогает отладке.
До знакомства с AVA, я писал тесты на Jasmine [4]. Мне нравится Behavior-Driven style. Для этого в AVA есть плагин ava-spec [5].
npm i -D ava-spec
После чего мы можем писать тесты так
import {describe} from 'ava-spec';
describe('module#1', it => {
it('can look almost like jasmine', t => {
t.deepEqual([1, 2], [1, 2]);
});
it.todo('todo');
it.skip('fail', t => {
t.fail();
});
});
Мы можем кастомизировать информацию о наших тестах. Мне понравился tap-summary [7].
npm i -D tap-summary
Используем
ava ava-spec.js -t | tap-summary
Сделаем функция, положим ее в отдельный файл, подключим и протестируем.
// ./test/sum.spec.js
import { describe } from 'ava-spec';
import sum from '../src/sum';
describe('sum', it => {
it('should return 10', t => {
const expected = 10;
const actual = sum(3, 7);
t.is(actual, expected);
});
});
// ./src/sum.js
function sum(x, y) {
return x + y;
}
module.exports = sum;
ava test/sum.spec.js
Все работает, наш код из файла подключен и протестирован. Но есть проблема, наш код написал на ES5, а тесты ES6. Давайте исправим эту ситуацию. AVA из коробки использует Babeljs [8]. И для нашего кода мы будет тоже использовать его. Настраиваем конфиги.
// .babelrc
{
"presets": [
"es2015"
]
}
и для AVA. Конфиг AVA находится прямо в package.json.
// ./package.json
...,
"ava": {
"babel": "inherit",
"require": [
"babel-register"
]
},
...
Запускаем без изменений.
ava test/sum.spec.js
AVA предоставляет отличную платформу для разработки тестов. В этой библиотеке есть все для этого: минималистичный стиль, быстрое выполнение, гибкость написания тестов, работа с тестами и окружением для них, информативный вывод ошибок. В сумме с возможностью кастомизировать как сам код тестов, исходя из предпочтений и необходимости, так и вывод информации по тестам.
Хотелось бы чуть чуть рассказать про автора этой библиотеки. Это, наверное, один из самых известных в JS сообществе людей Синдре Сорхус [9]. На его странице на github вы можете посмотреть на его проекты и в клад в сообщество. И/или вы можете познакомиться с ним как с человеком, на сколько это возможно в интернете, или задать вопрос/ы через ama — Ask me anything! [10].
Полезные ссылки:
Автор: alekseyleshko
Источник [14]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/202419
Ссылки в тексте:
[1] AVA: https://github.com/avajs/ava
[2] Pageres: https://github.com/sindresorhus/pageres
[3] тестирование было перенесено на AVA: https://github.com/sindresorhus/pageres/commit/663be15acb3dd2eb0f71b1956ef28c2cd3fdeed0
[4] Jasmine: http://jasmine.github.io/
[5] ava-spec: https://github.com/sheerun/ava-spec
[6] TAP — Test Anything Protocol: https://testanything.org/
[7] tap-summary: https://github.com/zoubin/tap-summary
[8] Babeljs: http://babeljs.io/
[9] Синдре Сорхус: https://github.com/sindresorhus
[10] ama — Ask me anything!: https://blog.sindresorhus.com/answering-anything-678ce5623798
[11] awesome-ava: https://github.com/avajs/awesome-ava
[12] awesome-tap: https://github.com/sindresorhus/awesome-tap
[13] Examples: https://github.com/AlekseyLeshko/ava-learn
[14] Источник: https://habrahabr.ru/post/313468/?utm_source=habrahabr&utm_medium=rss&utm_campaign=sandbox
Нажмите здесь для печати.