Предисловие
Привет, Хабр! Данная задача возникла у меня с проблемой, которая заключалась в создании робота для авторизации в Instagram, который бы делал за меня лайки. Всю задачу не напишу, напишу только часть реализации в виде настройки необходимого инструментария на удаленном сервере.
WEB — тестирование — это объемная и неоднозначная сфера, которая может заключаться в решении задач не только в плане тестирования WEB — приложений, но и, к примеру, в плане построения парсеров, роботов IoT и ботов работы с социальными сетями и все это используя только JavaScript!
Возможно, что вам не нравится словосочетание «тестирование», возможно, отчасти, из-за того, что это словосочетание заключает в себе более интересные вещи, которые, к примеру, позволят нам написать бота, способного авторизироваться в Instagram, Facebook и совершать там ряд действий от нашего лица и в одно и то же время нудно заниматься наблюдением, как выполняется наш фронтенд, но тестирование имеет смысл и уже стандартизировано сообществом W3C и продолжает развиваться.
Описание задачи в двух словах
Какую задачу мы ставим, чтобы решить при помощи тестирования? Всего-то нужно, чтобы какая-то программа открывала браузер и там автоматически кликала ссылки, вбивала тексты и показывала, что получится или возвращала параметр результата, который нам нужен. И все это нужно сделать на Linux — дистрибутиве Ubuntu 16.04, у которого нет GUI, т.е. у нас только консоль и запустить привычный браузер, как на полноценном компьютере не получится.
Что нужно для решения тестирования без GUI?
Все, что нужно для современного, «монопольного» тестирования на JavaScript:
- Headless Chromium Browser v 59 (chromium-browser) — безголовый браузер в консоли;
- Node.js (nodejs) — сервер JavaScript;
- WebDriver (chromedriver) — драйвер для обработки тестов на JavaScript и работы с chromium-browser посредством Node.js;
- Nightwatch.js (nightwatch) — известная библиотека для написания и запуска автотестов посредством Node.js от LinkedIn.
Установка на сервер
Напишем шаги для последовательной установки всех компонентов для тестирования.
1). Установка cromium-browser. Перед установкой chromium-browser надо будет установить все необходимые для него зависимости, поэтому надо будет выполнить ряд действий.
Устанавливаем зависимости:
sudo apt-get -f install
Если у нас были первые попытки установки, но помещали отсутствие зависимостей, то будет хорошо, если удалить загруженные файлы в /var/cache/apt/archives запуском команды:
sudo rm /var/cache/apt/archives/chromium*
Теперь устанавливаем сам cromium-browser:
sudo apt-get install chromium-browser
2). Установка nodejs. Как установить Node.js и все методы установки подробно описано тут.
Один из самых простых методов установки:
Есть вероятность, что данным методом установится старая стабильная версия v4.2.6 из репозитория Ubuntu, под которым этот пример тестирования не проверен. Для стабильной работы оптимально, если установить версию 7 или выше методом PPA или NVM
sudo apt-get update
sudo apt-get install nodejs
Также потребуется и менеджер пакетов, посредством которого надо будет установить chromedriver и nightwatch :
sudo apt-get install npm
Они нужны будут нам обработать тесты на JavaScript из Node.js.
3). Установка chromedriver. Этот драйвер выполняет роль WebDriver’а, предоставляющего API, к примеру, чтобы иметь возможность кликать на ссылки и вбивать тексты в текстовые поля и формы, для этого мы и будем использовать Chromedriver. Для установки chromedriver выполняем команду:
npm install chromedriver
4). Установка nightwatch. Nightwatch.js — это библиотека для написания и запуска автотестов на JavaScript:
npm install nightwatch
Схема работы тестирования
Коротко вся схема выглядит таким образом, что тесты на Nightwatch.js отправляют запросы на Chromedriver, а Chromedriver обращается к Chrome Browser для исполнения тестов(заполнение полей форм и нажатие на ссылки):
Настройка и запуск первого теста
Конфигурационный файл Nightwatch.js умолчанию находится в папке node_modules/nightwatch/bin и настройки берутся по умолчанию оттуда и для того, чтобы задать наши пользовательские настройки для Nightwatch.js нужно создать файл nightwatch.json в корне проекта и прописать туда всё необходимое, чтобы Chromedriver использовался напрямую (без Selenium и других сторонних вещей) и Chromium запускался в «headless» режиме:
{
"src_folders": ["tests"], // путь к папке с тестами
"output_folder": "reports",
"custom_commands_path": "",
"custom_assertions_path": "",
"page_objects_path": "",
"globals_path": "globals.js", // путь к файлу, в котором задаётся глобальный контекст для всех тестов
"selenium": {
"start_process": false // отменяем запуск Селениума, т.к. будем обращаться к Chromedriver напрямую
},
"test_settings": {
"default": {
"selenium_port": 9515, // номер порта Chromedriver по умолчанию ("selenium_" в имени поля — это пережиток прошлого)
"selenium_host": "localhost",
"default_path_prefix" : "",
"desiredCapabilities": {
"browserName": "chrome",
"chromeOptions" : {
"args" : ["--no-sandbox", "--headless", "--disable-gpu"], // специальные флаги для работы Хрома в headless-режиме
"binary" : "/usr/bin/chromium-browser" // путь к исполняемому файлу Хрома
},
"acceptSslCerts": true
}
}
}
}
Нужно обратить внимание на строку с globals.js. Внутри этого файла можно задать глобальный контекст для всех тестов. Пропишем туда, чтобы Chromedriver стартовал перед запуском всех тестов и прибивался в конце:
const chromedriver = require('chromedriver');
module.exports = {
before: function(done) {
chromedriver.start();
done();
},
after: function(done) {
chromedriver.stop();
done();
}
};
Теперь необходимо написать любой тест для проверки работоспособности системы тестирования. К примеру, нужно открыть google.com, поискать что-нибудь и проверить результаты поиска. Конечно, Nightwatch.js API предоставляет ещё кучу всяких методов для всевозможных проверок, но для начала нам хватит:
module.exports = {
'Test google.com': function(browser) {
const firstResultSelector = '#rso cite._Rm';
browser
.url('http://google.com', () => {
console.log('Loading google.com...');
})
.waitForElementVisible('#lst-ib', 5000)
.execute(function() {
document.getElementById('lst-ib').value = 'Блог WebSofter!';
})
.submitForm('form')
.waitForElementVisible(firstResultSelector, 5000)
.getText(firstResultSelector, result => {
browser.assert.equal(result.value, 'blog.websofter.ru/');
})
.end();
}
};
Запускаем через консоль по команде:
nightwatch --test google.js
Замечание. Во первых, если Node.js установлен через nvm, то надо активировать сессию через команду:
nvm ~/.profile
во вторых, для запуска теста необходимо создать в корне проекта package.json с данными проекта, а в виде запускаемого фала надо указать google.js через команду:
npm init
Далее уже выполняем команду запуска нашего теста:
nightwatch --test google.js
Результатом выше изложенного кода в файлах будет результат в консоли:
Т.е., мы заходим на главную сайта Google, вбиваем в поиск словосочетание «Блог WebSofter!» и в итоге сравнивается адрес нашего блога на наличие в определенных тегах на странице результата поиска.
Скачать рабочий пример из этой статьи можно по ссылке.
Заключение
Первоначально Nightwatch.js был ориентирован на работу с Selenium. Но сегодня она умеет работать с chromedriver напрямую и необходимость в Selenium тем более в PhantomJS отпадает, хотя есть возможность с ними интегрировать.
Осторожно! Безголовый режим Chrome доступен на Mac и Linux в v59. Поддержка Windows входит в Chrome v60. Чтобы проверить, какая версия Chrome у вас есть, откройте
chrome://version
Безголовый Chrome поставляется в версии Chrome 59. Это способ запуска браузера Chrome в безголовой среде, т.е. в консоли без GUI. Подобным образом работал PhantomJS. Chrome привносит в командную строку все современные функции веб-платформы, предоставляемые Chromium и движком Blink.
Почему это полезно?
Безголовый браузер — отличный инструмент для автоматического тестирования и серверных сред, где вам не нужна видимая оболочка пользовательского интерфейса. Например, вы можете выполнить некоторые тесты на реальной веб-странице, создать PDF-файл или просто проверить, как браузер отображает URL-адрес. Дополнительно можно узнать по ссылке
prefrontalCortex
Спасибо за статью!
Боюсь, вы только что случайно бутылку колы.
suratovvlad
Мне кажется, что, наверняка, для этого уже есть Docker образ на хабе :)
ihost
Конечно, Nightwatch в целом неплох, но имеет свои недостатки: устаревший синтаксис с callback-цепочками вместо Promises и async/await, и требования наличия webdriver-а к браузеру — как тестировать на смартфоне или смарт-ТВ? Если Вы занимаетесь функциональным тестированием web-сфере и следите за развитием технологий, рекоммендую ознакомиться с этой статьей, и в частности, присмотреться к решениям от TestCafe — тоже на Node.js, но поудобнее и решающий вопрос с любыми девайсами. Можно вообще SauseLabs прикрутить, чтобы тестировать на всевозможных устройствах скопом.
EvilsInterrupt
Да, TestCafe выглядит не плохим. Но! Присмотритесь по-внимательнее:
«TestCafe uses a URL-rewriting proxy which allows it to work without the WebDriver. This proxy injects the driver script that emulates user actions into the tested page.». © FAQ I have heard that TestCafe does not use Selenium. How does it operate?
Меня, если честно, очень коробит, когда тест.программа лезет в тестируемый объект. Да, бывают случаи, когда без модификации тест.объекта нет возможности проверить ту или иную функциональность, но когда есть зачем это надо делать? Я к тому что Selenium-based решения сейчас более выигрышные!
ihost
Безусловно, у всех решений свои плюсы и минусы. В принципе, в современном web-е код модифицируется и так немало раз — babel для async/await и генераторов, bundle-ирование в webpack-е, polyfills и так далее — так что в принципе в еще одном преобразовании особо ничего страшного нет.
Сам hammerhead выглядит довольно надежным — мне удалось найти, как выйти из песочницы, но маловероятно, что в обычном web-приложении такое бывает. Зато пользователи SmartTV и прочих необычных браузеров счастливы :)
EvilsInterrupt
Не спорю! Но. Все эти преобразования дают итоговый продукт. Вот именно итоговый продукт и есть тест. объект, который желательно не трогать и проверять таким какой он есть. Иначе может получиться ситуация, что у разработчика одна ситуация, а пользователя совсем другая. Я сейчас про конечного продукта, т.е. по принципу черного ящика, а не серо или бело ящичные виды тестирования
vados665
Спасибо большое! Как раз искал что то в этом духе)
AlexPTS
Исследовал множество инструментов для тестирования на nodejs и выбрал nightwatchjs. Много лет применял nightwatchjs в работе в разных компаниях, но на текущий день его сложно рекомендовать новым людям из-за отсутствия поддержки async/await из коробки, которые помогают писать тест как «синхронный» код, делая тесты лаконичнее в синтаксисе и проще для восприятия и понимания.
В эпоху ES6 стоит 2 раза подумать об этом, прежде чем делать свой выбор в пользу того или иного инструмента.