- PVSM.RU - https://www.pvsm.ru -

Доставляем себе в офис чашку горячего кофе одной командой консоли с помощью TestCafe

Доставляем себе в офис чашку горячего кофе одной командой консоли с помощью TestCafe - 1 [1]

Друзья, сегодня я расскажу вам историю о том, как просто и изящно решить проблему еnd-to-еnd тестирования web-сервиса доставки кофе [2] с помощью нового open source тестового фреймворка. Мы проведем проверку не только работы сайта, но и менеджеров и даже службы доставки, к тому же потратим на это минимум усилий и времени. А в качестве бонуса за приложенные усилия получим кружечку горячего кофе прямо в руки. Всех любителей приключений прошу под кат…

На сегодняшний день необходимость e2e web-тестирования уже ни для кого не новость. Вопрос о выборе сервиса для тестирования рано или поздно встает ребром для любого web-приложения. Широкой публике известны различные Selenium-производные решения, подавляющее большинство которых построено на использовании WebDriver. Мы же собираемся продемонстрировать работу с новым open source тестовым фреймворком TestCafe [3], построенным на совершенно ином принципе. Перейдем же, наконец, от разговоров к делу.

Установка TestCafe

Как всегда начинается все с установки продукта. Это конечно совсем скучно, но я вас обрадую, полная установка TestCafe выполняется всего одной командой консоли.

npm install -g testcafe

Если вам приходилось устанавливать Selenium или базирующиеся на нем фреймворки, то вы приятно удивитесь насколько просто и быстро это делать c TestCafe. Как вы могли заметить, TestCafe построен на Node.js [4], а это значит — никаких 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 [5], транслирует весь код в синтаксис 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 берет все эти обязанности на себя, вам больше не нужно беспокоиться об этом.

Для указания элементов, с которыми необходимо провести действия, мы воспользовались селекторами [6]. Селекторы в TestCafe позволяют проделывать всю работу, связанную с DOM элементами. Для этого необходимо указать способ получения элемента на клиенте, например, css — селектор или функцию. А также TestCafe предоставляет API для создания составных селекторов [7], которые позволяют находить элемент по расположению в иерархии страницы или по заданным фильтрам (текст, индекс и любые кастомные фильтры).

После того как мы перешли в необходимое нам меню, добавим в корзину чашечку "классического Латте":
image

await t.click(Selector('.title').withText('Латте классический').sibling('.labels'));

Проверка состояния элементов страницы

Теперь нам необходимо убедиться, что товар добавлен в корзину. Перейдем на соответствующую страницу:

await t.click('.myShop-cartmini');

Для проверки используем предоставляемые TestCafe встроенные assertion-ы [8]. А чтобы получить значение интересующего нас свойства элемента страницы снова воспользуемся селекторами. Селекторы содержат набор асинхронных свойств и методов [9], которые можно непосредственно исполнить в тесте или передать в assertion. Во втором случае assertion-ы активируют механизм ожидания [10]. Ведь очень часто необходимо дождаться завершения анимации, или получения ответа на 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('Доставка');

Выполнение кода на клиенте

Мы также можем воспользоваться клиентской функцией [11] для получения количества товаров в корзине. Исполняться такая функция будет на клиенте, а результат вернет на сервер. Внутри клиентской функции может быть использован любой js код, как если бы вы просто добавили его на страницу.

const getOderCount = ClientFunction(() => document.querySelectorAll('.myShop-cart-item').length);

let orderCount = await getOderCount();

Существует также способ немедленного исполнения кода на клиенте — использование метода t.eval [12].

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, а, при указании соответствующей опции [13], еще и ссылку на скриншот, сделанный при падении. Таким образом благодаря TestCafe мы смогли найти ошибку написав всего один несложный тест. Обнаружив ошибку мы сообщили об этом владельцам сайта и посоветовали использовать TestCafe для тестирования, чтобы избежать появления ошибок в дальнейшем :).

Запустим выполнение теста без падения на ошибках страницы следующей командой консоли:

testcafe chrome get-a-cup-of-coffee.js --skip-js-errors 

image
Отчеты о прохождении тестов могут быть представлены в различных форматах [14], для этого существуют набор соответствующих плагинов. Они позволяют настроить работу с основными системами непрерывной интеграции. Вы можете запускать тесты не только на локальных, но и на удаленных и облачных устройствах (например Sauce Labs [15]). Для окончательной автоматизации нашего сервиса нам осталось интегрировать полученный результат в систему непрерывной интеграции. Кто знает, возможно в будущем нам захочется добавить проверку температуры кофе, времени его доставки или даже его вкуса. Про автоматизации и интеграцию этого процесса мы, пожалуй, напишем отдельную статью :).

Выводы

Как видите, мы добились первоначальной цели: одной командой мы заказали себе кофе прямо в офис и подтвердили эффективность работы сервиса. Конечно это шутливый пример, мы взяли компанию, которая осуществляет доставку кофе всего в четырех городах. Но вы можете написать простенький тест для любого подобного сервиса, находящегося у вас под боком.

Готовый пример можно найти здесь [16]. Мы использовали методологию PageObject [17], которая позволяет сделать код теста более читаемым и понятным.

Надеюсь после прочтения вы заглянете к нам в TestCafe [18] на чашечку кофе. Обсудить все интересующие вопросы можно в комментариях или на discuss [19]. Кофейного вам дня!

Автор: elena_dikareva

Источник [20]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/javascript/233969

Ссылки в тексте:

[1] Image: https://habrahabr.ru/post/318452/

[2] web-сервиса доставки кофе: http://www.pitcofe.ru/

[3] TestCafe: https://devexpress.github.io/testcafe

[4] Node.js: https://nodejs.org/en/

[5] Babel: https://babeljs.io/

[6] селекторами: https://devexpress.github.io/testcafe/documentation/test-api/selecting-page-elements/selectors.html

[7] API для создания составных селекторов: https://devexpress.github.io/testcafe/documentation/test-api/selecting-page-elements/selectors.html#combined-selectors

[8] assertion-ы: https://devexpress.github.io/testcafe/documentation/test-api/assertions/

[9] набор асинхронных свойств и методов: https://devexpress.github.io/testcafe/documentation/test-api/selecting-page-elements/selectors.html#obtain-element-state

[10] механизм ожидания: https://devexpress.github.io/testcafe/documentation/test-api/assertions/#smart-assertion-query-mechanism

[11] клиентской функцией: https://devexpress.github.io/testcafe/documentation/test-api/obtaining-data-from-the-client.html

[12] t.eval: https://devexpress.github.io/testcafe/documentation/test-api/obtaining-data-from-the-client.html#one-time-client-code-execution

[13] опции: https://devexpress.github.io/testcafe/documentation/using-testcafe/command-line-interface.html

[14] форматах: https://devexpress.github.io/testcafe/documentation/using-testcafe/common-concepts/reporters.html

[15] Sauce Labs: https://devexpress.github.io/testcafe/documentation/using-testcafe/common-concepts/browser-support.html#browsers-in-cloud-testing-services

[16] здесь: https://github.com/helen-dikareva/get-a-cup-of-coffee/blob/master/test.js

[17] PageObject: http://martinfowler.com/bliki/PageObject.html

[18] TestCafe: https://devexpress.github.io/testcafe/

[19] discuss: https://testcafe-discuss.devexpress.com/

[20] Источник: https://habrahabr.ru/post/318452/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best