AVA — Футуристична JavaScript бібліотека для тестування

У цій статті я хочу представити вам нову бібліотеку для тестування ВІДКРИТИ. Відносно нову, їй вже більше 2-х років, і вона обзавелася солідним кількістю плагінів і звичайно ж співтовариством що її розвиває. Ми подивимося на функціонал бібліотеки. Налаштуємо оточення і напишемо пару тестів, щоб подивитися на бібліотеку в дії.
Що ж пропонує AVA?
В першу чергу бібліотека пропонує швидкість. Тести запускаються паралельно, що дає прискорення виконання тестів. В якості прикладу приводиться проект Pageres, в якому тестування було перенесено на AVA, що дало збільшення майже в 3 рази(31 секунда було і стало 11). Тести не залежать від глобального стану і від інших тестів, що звичайно ж спрощує тестування. З коробки відразу йде використання es2015.
Що потрібно зробити щоб почати користуватися AVA вже зараз?
Встановити відповідний npm модуль. Встановимо як залежність для роботи в конкретній папці.
// package.json
...,
"scripts": {
"test": "ava"
},
...

npm install -D ava
npm test

або глобально
npm i -g ava
ava

Запуск тестів
Настав час написати перший тест, візьмемо приклад з офіційного репозиторію. І зберегти його як my-tests.js
import test from 'відкрити';

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 passed tests

Так само ми можемо запустити watcher, щоб розробляти в стилі TDD
ava my-tests.js --watch
// or
ava my-tests.js -w

Поспотреть повний список параметрів можна
ava --help

API бібліотеки
Простий тест:
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 'відкрити';
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 passed tests

І бачимо, що тести запустилися і закінчилися успішно. Але це не правильно, даних код не гарантує виконання в потрібне нам порядку. Якщо ми зімітуємо ситуацію коли файлу ще немає, 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 passed tests

Або
test.cb.serial('serial 1', t => {
...
});

Тест падає і ми про це знаємо. Ми можемо про це явно вказати.
test.failing('failing', t => {
t.fail();
});

В результаті бачимо, що цей тест падає, але ми знаємо про це, і в ідеалі вже, що то робимо.
1 known failure

Дуже приємно, що ми можемо поєднувати параметри. Це дозволяє нам реалізувати будь-якої складності тести і запускати тільки необхідні і в потрібному порядку.
test.only.cb
test.cb.only

Before і After
Для налаштування оточення тестів є 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
Коли нам потрібно налаштовувати оточення перед кожен тестом використовуємо beforeEach і afterEach.
test.beforeEach(t => {
});
test.afterEach(t => {
});

Для них зберігається поведінку як і для before і after: порядок оголошення та при помилку в тесті after не викликаються(якщо немає always).
Assertions
test('test', t => {
t.pass();
t.skip.fail();
t.truthy(true);
t.truthy('unicorn');
t.falsy(false);
t.falsy(1 === 0);
t.true(істина);
t.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. Мені подобається Behavior-Driven style. Для цього в AVA є плагін ava-spec.
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('all');

it.skip('fail', t => {
t.fail();
});
});

TAP — Test Anything Protocol
Ми можемо кастомизировать інформацію про наших тестах. Мені сподобався tap-summary.
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('сума', 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. І для нашого коду ми теж буде використовувати його. Налаштовуємо конфіги.
// .babelrc
{
"presets": [
"es2015"
]
}

і для AVA. Конфіг AVA знаходиться прямо в package.json.
// ./package.json
...,
"ava": {
"babel": "inherit",
"require": [
"babel-register"
]
},
...

Запускаємо без змін.
ava test/sum.spec.js

Підсумок
AVA надає відмінну платформу для розробки тестів. У цій бібліотеці є все для цього: мінімалістичний стиль, швидке виконання, гнучкість написання тестів, робота з тестами і оточенням для них, інформативний висновок помилок. В сумі з можливістю кастомизировать як сам код тестів, виходячи з переваг та необхідності, так і висновок інформації щодо тестів.
Про автора бібліотеки
Хотілося б трохи розповісти про автора цієї бібліотеки. Це, напевно, один з найбільш відомих в JS співтоваристві людей Синдре Сорхус. На його сторінці на github ви можете подивитися на його проекти і скарб у співтовариство. І/або ви можете познайомитися з ним як з людиною, на скільки це можливо в інтернеті, або поставити запитання/и через ama — Ask me anything!.

p.s.

  • корисних посиланнях останній репозиторій з прикладами для статті.
  • Від себе: після знайомства з AVA, я перейшов у своїх нових домашніх проектах на AVA. Наступний робочий проект буде розроблятися з цією бібліотекою. Можливо деякі старі свої проекти переведу на AVA заодно замерю швидкість виконання і складність переходу.
Корисні посилання:
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.