Доставляємо собі в офіс чашку гарячої кави однією командою консолі за допомогою TestCafe


Друзі, сьогодні я розповім вам історію про те, як просто і елегантно вирішити проблему еnd-to-еnd тестування web-сервісу доставки кави з допомогою нового open source тестового фреймворка. Ми проведемо перевірку не тільки роботи сайту, але і менеджерів і навіть служби доставки, до того ж витратимо на це мінімум зусиль і часу. А в якості бонусу за докладені зусилля отримаємо чашку гарячої кави прямо в руки. Всіх любителів пригод прошу під кат...
На сьогоднішній день необхідність e2e web-тестування вже ні для кого не новина. Питання про вибір сервісу для тестування рано або пізно встає ребром для будь-якого web-додатки. Широкій публіці відомі різні Selenium-похідні рішення, переважна більшість яких побудовано на використанні WebDriver. Ми ж збираємося продемонструвати роботу з новим open source тестовим фреймворком TestCafe, побудованим на зовсім іншому принципі. Перейдемо ж, нарешті, від розмов до справи.
Установка TestCafe
Як завжди все починається з установки продукту. Це звичайно зовсім нудно, але я вас порадую, повна установка TestCafe виконується лише однією командою консолі.
npm install -g testcafe

Якщо вам доводилося встановлювати Selenium або базуються на ньому фреймворки, то ви приємно здивуєтеся наскільки просто і швидко це робити c TestCafe. Як ви могли помітити, TestCafe побудований на Node.js, а це означає — жодних Java, ніяких плагінів для браузера або прив'язок до операційної системи. Все, що вам необхідно, це мати Node.js на своєму комп'ютері.
Тепер створимо файл, в якому буде знаходитися наш тест, назвемо його get-a-cup-of-coffee.js. У файлі створимо fixture — набір тестів, вкажемо адресу сторінки і створимо порожній тест.
fixture `Let\'s take a look at the new TestCafe`
.page `http://www.pitcofe.ru/`;

test(`Get a cup of coffee`, async t => {
// TODO: test
});

Однією з приємних особливостей TestCafe фреймворку є те, що в тесті ви можете використовувати ES6 і ES7 синтаксис, незалежно від того, чи підтримує його браузер або ваша версія Node.js. TestСafe, за допомогою Babel, транслює весь код в синтаксис ES5.
Написання тесту
Виконання дій з елементами сторінки
Приступимо до написання тесту. Перейдемо в розділ доставки гарячої кави. Все гранично просто — натискаємо на пункт "Меню" і вибираємо пункт "Кава".
image
test(`Get a cup of coffee`, async t => {
await t
.click(Selector('#nav').find('a').withText('меню'))
.click(Selector('#content').find('#smenu-150'));
});

Зверніть увагу, під час тесту відбудеться кілька переходів на нові сторінки. Але, як ви переконаєтеся самі, ніде в тесті ми не будемо вказувати, в який момент і як довго потрібно чекати завантаження сторінки, відправку форми або відповіді на XHR запит. TestCafe бере всі ці обов'язки на себе, вам більше не потрібно турбуватися про це.
Для вказівки елементів, з якими необхідно провести дії, ми скористалися селекторами. Селектори в TestCafe дозволяють виконувати всю роботу, пов'язану з DOM елементами. Для цього необхідно вказати спосіб отримання елемента на клієнта, наприклад, css — селектор або функцію. А також TestCafe надає API для створення складових селекторів, які дозволяють знаходити елемент по розташуванню в ієрархії сторінки або по заданим фільтрів (текст, індекс і будь-які кастомні фільтри).
Після того як ми перейшли в необхідне нам меню, додамо в кошик чашечку "класичного Латте":
image
await t.click(Selector('.title').withText('Латте класичний').sibling('.labels'));

Перевірка стану елементів сторінки
Тепер нам необхідно переконатися, що товар доданий в корзину. Перейдемо на відповідну сторінку:
await t.click('.myShop-cartmini');

Для перевірки використовуємо надаються TestCafe вбудовані assertion-ы. А щоб отримати значення цікавлячого нас властивості елемента сторінки знову скористаємося селекторами. Селектори містять набір асинхронних властивостей і методів, які можна безпосередньо виконати в тісті або передати в assertion. У другому випадку assertion-и активують механізм очікування. Адже дуже часто необхідно дочекатися завершення анімації, або отримання відповіді на XHR запит перш, ніж виконувати assertion.
Всі існуючі бібліотеки assertion-ів передбачають використання штучних затримок, що сильно збільшує час проходження тестів і робить їх нестабільними. TestCafe дбає про це сам. Якщо при використанні властивості і методу селектора перевірка не проходить, тест не падає миттєво. Assertion-и обчислюється кілька разів, на кожній ітерації отримуючи актуальне значення і падає тільки в тому випадку, якщо досягнуто таймаут та перевірка так і не виконалася успішно. Такий підхід дозволяє писати стабільні, швидкі і надійні тести, не замислюючись про час відгуку досліджуваної сторінки.
Перевіримо число і найменування товарів в кошику.
image
const items = Selector('.myShop-cart-item');

await t
.expect(items.count).eql(2)
.expect(items.nth(0).innerText).contains('Латте класичний')
.expect(items.nth(1).innerText).contains('Доставка');

Виконання коду на клієнті
Ми також можемо скористатися клієнтської функцією для отримання кількості товарів в кошику. Виконуватися така функція буде на клієнті, а результат поверне на сервер. Всередині клієнтської функції може бути використаний будь-який js код, як якщо б ви просто додали її на сторінку.
const getOderCount = ClientFunction(() => document.querySelectorAll('.myShop-cart-item').length);

let orderCount = await getOderCount();

Існує також спосіб негайного виконання коду на клієнті — використання методу t.eval.
orderCount = await t.eval(() => document.querySelectorAll('.myShop-cart-item').length);

Перевіримо, що отримані дані відповідають нашим очікуванням.
await t.expect(orderCount).eql(2);

Завершення і оформлення замовлення
Повернемося в меню вибору кави і додамо в кошик чашечку «Флет Уайт Попкорн»:
image
await t
.click('.myShop-cartmini')
.click(Selector('#content').find('#smenu-150'))
.click(Selector('.title').withText('Флет уайт попкорн').sibling('.labels'));

Знову перейдемо в кошик і перевіримо, що число і найменування товарів змінилося.
await t
.click('.myShop-cartmini')
.expect(Selector('.myShop-cart-item').count).eql(3)
.expect(Selector('.myShop-cart-item').nth(0).innerText).contains('Латте класичний')
.expect(Selector('.myShop-cart-item').nth(1).innerText).contains('Флет уайт попкорн')
.expect(Selector('.myShop-cart-item').nth(2).innerText).contains('Доставка');

Тепер завершимо оформлення замовлення — перейдемо на сторінку заповнення контактних даних та адреси доставки. Заповнивши необхідні поля залишиться тільки натиснути кнопку "Відправити".
image
await t
.click('.myShop-button-order')
.typeText('#ffio', 'Ім'я')
.typeText('#ftel', '+79999999999')
.click('#fgorod')
.click(Selector('#fgorod > option').withText('Ростов-на-Дону'))
.typeText('#fulica', 'Леніна')
.typeText('#fdom', '1')
.click('input[type="submit"]');

Тест готовий. У коді немає нічого зайвого, він містить тільки перелік вироблених дій і роботу з елементами сторінки, при цьому залишається зрозумілим для читання і супроводу.
Запуск тесту
Запустимо тест наступною командою консолі:
testcafe chrome get-a-cup-of-coffee.js

TestCafe знайде встановлений на машині браузер, сам запустить його і виконає тест.
В консоль буде надана детальна інформація про результати проходження тесту.
image
Тест впав через помилку на сайті. У разі падіння тесту TestCafe надає callsite і callstack, а, при вказівці відповідної опциище й посилання на скріншот, зроблений при падінні. Таким чином завдяки TestCafe ми змогли знайти помилку написавши всього один нескладний тест. Виявивши помилку ми повідомили про це власника сайту і порадили використовувати TestCafe для тестування, щоб уникнути появи помилок надалі :).
Запустимо виконання тесту без падіння на помилках сторінки наступною командою консолі:
testcafe chrome get-a-cup-of-coffee.js --skip-js-errors 

image
Звіти про проходження тестів можуть бути представлені в різних форматахдля цього існують набір відповідних плагінів. Вони дозволяють налаштувати роботу з основними системами безперервної інтеграції. Ви можете запускати тести не лише локальних, але і на віддалених і хмарних пристроях (наприклад, Sauce Labs). Для остаточної автоматизації нашого сервісу нам залишилося інтегрувати отриманий результат в систему безперервної інтеграції. Хто знає, можливо, в майбутньому нам захочеться додати перевірку температури кави, часу його доставки чи навіть його смаку. Про автоматизації і інтеграцію цього процесу ми, мабуть, напишемо окрему статтю :).
Висновки
Як бачите, ми домоглися первісної мети: однією командою ми замовили собі каву прямо в офіс і підтвердили ефективність роботи сервісу. Звичайно це жартівливий приклад, ми взяли компанію, яка здійснює доставку кави всього в чотирьох містах. Але ви можете написати простенький тест для будь-якого подібного сервісу, що знаходиться у вас під боком.
Готовий приклад можна знайти на тут. Ми використовували методологію PageObject, яка дозволяє зробити код тесту більш читабельним і зрозумілим.
Сподіваюся, після прочитання ви завітаєте до нас в TestCafe на чашечку кави. Обговорити всі питання можна в коментарях або на discuss. Кавового вам дня!
Джерело: Хабрахабр

0 коментарів

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