- PVSM.RU - https://www.pvsm.ru -
Друзья, сегодня я расскажу вам историю о том, как просто и изящно решить проблему еnd-to-еnd тестирования web-сервиса доставки кофе [2] с помощью нового open source тестового фреймворка. Мы проведем проверку не только работы сайта, но и менеджеров и даже службы доставки, к тому же потратим на это минимум усилий и времени. А в качестве бонуса за приложенные усилия получим кружечку горячего кофе прямо в руки. Всех любителей приключений прошу под кат…
На сегодняшний день необходимость e2e web-тестирования уже ни для кого не новость. Вопрос о выборе сервиса для тестирования рано или поздно встает ребром для любого web-приложения. Широкой публике известны различные Selenium-производные решения, подавляющее большинство которых построено на использовании WebDriver. Мы же собираемся продемонстрировать работу с новым open source тестовым фреймворком TestCafe [3], построенным на совершенно ином принципе. Перейдем же, наконец, от разговоров к делу.
Как всегда начинается все с установки продукта. Это конечно совсем скучно, но я вас обрадую, полная установка 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.
Приступим к написанию теста. Перейдем в раздел доставки горячего кофе. Все предельно просто — нажимаем на пункт "Меню" и выбираем пункт "Кофе".
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], которые позволяют находить элемент по расположению в иерархии страницы или по заданным фильтрам (текст, индекс и любые кастомные фильтры).
После того как мы перешли в необходимое нам меню, добавим в корзину чашечку "классического Латте":
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-ы вычисляется несколько раз, на каждой итерации получая актуальное значение и падает только в том случае, если достигнут таймаут и проверка так и не выполнилась успешно. Такой подход позволяет писать стабильные, быстрые и надежные тесты, не задумываясь о времени отклика тестируемой страницы.
Проверим число и наименование товаров в корзине.
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);
Вернемся в меню выбора кофе и добавим в корзину чашечку “Флэт Уайт Попкорн”:
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('Доставка');
Теперь завершим оформление заказа — перейдем на страницу заполнения контактных данных и адреса доставки. Заполнив необходимые поля останется только нажать кнопку "Отправить".
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 найдет установленный на машине браузер, сам запустит его и выполнит тест.
В консоль будет выдана подробная информация о результатах прохождения теста.
Тест упал из-за ошибки на сайте. В случае падения теста TestCafe предоставляет callsite и callstack, а, при указании соответствующей опции [13], еще и ссылку на скриншот, сделанный при падении. Таким образом благодаря TestCafe мы смогли найти ошибку написав всего один несложный тест. Обнаружив ошибку мы сообщили об этом владельцам сайта и посоветовали использовать TestCafe для тестирования, чтобы избежать появления ошибок в дальнейшем :).
Запустим выполнение теста без падения на ошибках страницы следующей командой консоли:
testcafe chrome get-a-cup-of-coffee.js --skip-js-errors
Отчеты о прохождении тестов могут быть представлены в различных форматах [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
Нажмите здесь для печати.