Запуск автоматизированных тестов веб-интерфейса с использованием WebdriverIO 18.04.2016

В этой статье мы поговорим о том, что потребуется для организации простейшего тестирования интерфейса веб-приложения. Мы будем использовать самую популярный инструмент, подходящий для этих целей — Selenium (http://www.seleniumhq.org). Selenium позволяет автоматизировать работу с браузером, поддерживает большинство браузерных платформ и предоставляет соответствующее API. Именно поэтому Selenium так популярен при разработке автоматизированных тестов. В качестве API для работы с Selenium мы будем использовать WebdriverIO (http://webdriver.io/) под Node.js. API WebdriverIO обладает удобным синтаксисом, заметно упрощающим разработку тестов. WebdriverIO можно использовать в связке как со сторонними тест-раннерами, так и с входящим в пакет WebdriverIO раннером wdio, разработанным специально для организации автоматизированного тестирования на базе WebdriverIO. Подробную информацию о wdio можно найти на сайте разработчика здесь.

Соответственно, для запуска тестов нам потребуется прежде всего Selenium Standalone Server, WebdriverIO в качестве API для взаимодействия с браузером, тест-раннер (мы разберем использование Webdriver в в двух связках — с раннером wdio и раннером Mocha), библиотека для описания тестов, а также такс-менеджер для организации процесса запуска тестов. Независимо от подхода, который мы будем рассматривать, нам понадобится библиотека для описания тестов, в качестве которой мы будем использовать Mocha. Mocha обладает двумя достоинствами, из-за которых мы будет использовать именно ее. Во-первых Mocha сама по себе является тест-раннером, а это избавляет нас от необходимости использовать дополнительные библиотеки в подходе без использования wdio. Во-вторых, достоинством Mocha как библиотеки для описания тестов является возможность использования произвольных библиотек ассертов (библиотек, предоставляющих функции сравнения результатов тестов с ожидаемыми).

Итак, приступим. Мы будем использовать Node.js, поэтому на вашей машине должна быть установлена актуальные версии Node.js и менеджера пакетов NPM.

WebdriverIO + Mocha testrunner

Установим необходимые зависимости.
Таск-менеджер Gulp http://gulpjs.com/:

npm install —save-dev gulp

Так же нам потребуется интерфейс Gulp для командной строки (https://www.npmjs.com/package/gulp-cli), который потребуется установить глобально:

npm install -g gulp-cli

Нам потребуется адаптер для использования Mocha при помощи Gulp (https://www.npmjs.com/package/gulp-mocha):

npm install —save-dev gulp-mocha

Сам selenium standalone server (https://www.npmjs.com/package/selenium-standalone):

npm install —save-dev selenium-standalone

собственно WebdriverIO (https://www.npmjs.com/package/webdriverio):

npm install —save-dev webdriverio

и простейшую библиотеку ассертов:

npm install —save-dev assert

Теперь, когда все необходимые нам библиотеки установлены, приступим к описанию процесса запуска тестов. В корне нашей директории создадим gulpfile.js.
Прежде всего, для запуска тестов нам необходимо установить и запустить инстанс Selenium Standalone Server. Соответствующее задание в gulpfile.js будет выглядеть примерно так.

var gulp = require('gulp'),

    selenium = require('selenium-standalone');

gulp.task('selenium', function (done) {

    selenium.install(

        {

            logger: function (message) {

                console.log(message);

            }

        },

        function (error) {

            if (error) return done(error);


            selenium.start(function (error, child) {

                if (error) return done(error);

                selenium.child = child;

                done();

            });

        }

    );

});

Здесь прежде всего стоит отметить вызовы selenium.install и selenium.start - установка и запуск сервера соотвественно. selenium.install при запуске проверяет наличие в node_modules/selenium-standalone установленного сервера и дарйверов для управления конкретными типами браузера. В случае их отсутствия он скачает и установит необходимые платформоспецифичные версии. В качестве первого параметра install получает объект с опциями, который использует при установке. Здесь можно указать версию сервера, которую требуется установить, а также браузеры, которыми планируется управлять - по-умолчанию будет остановлен драйвер для управления браузером Chrome. Единственным обязательным полем является logger. Указав в нем функцию вывода сообщений в консоль, в будущем можно будет убедиться, какие операции выполняет install. Более подробную информацию о настройках установки selenium standalone server под Node.js можно прочитать здесь. В качестве второго параметра install принимает коллбэк, который будет вызван по завершении установки. Мы, соответственно, по завершении установки и в случае отсутствия ошибок запускаем инстанс Selenium Standalone Server вызовом метода start, по исполнении которого сохраняем запущенный процесс в поле selenium.child.

Теперь создадим задание описывающее запуск тестов при помощи Mocha:

var gulp = require('gulp'),

    mocha = require('gulp-mocha');

gulp.task('mocha', ['selenium'], function () {

    return gulp

        .src('tests/**/*Test.js', {read: false})

        .pipe(mocha());

});

Отметим, что так mocha требует выполнение таска selenium, который мы описали выше. Таск передает на обработку Mocha все файлы из папки tests, название которых оканчивается на Test.js.

Задание, запускающее тесты, будет выглядеть примерно так:

gulp.task('test', ['mocha'], function () {

    selenium.child.kill();

});

Таск запускает выполнение таска mocha и, по его завершении убивает серверный процесс.

Полный код gulpfile.js будет выглядеть так:

var gulp = require('gulp'),

    selenium = require('selenium-standalone'),

    mocha = require('gulp-mocha');



gulp.task('selenium', function (done) {

    selenium.install(

        {

            logger: function (message) {

                console.log(message);

            }

        },

        function (error) {

            if (error) return done(error);


            selenium.start(function (error, child) {

                if (error) return done(error);

                selenium.child = child;

                done();

            });

        }

    );

});



gulp.task('mocha', ['selenium'], function () {

    return gulp

        .src('tests/**/*Test.js', {read: false})

        .pipe(mocha());

});



gulp.task('test', ['mocha'], function () {

    selenium.child.kill();

});

Теперь тесты можно запустить командой:

gulp test

Для демонстрации создадим простейший тест: запускаем браузер, открываем в нем страницу Google.com, проверяем соответствие заголовка страницы тексту "Google", закрываем браузер.
Тест поместим в файл tests/ExempleTest.js. Код теста будет выглядеть так:

var assert = require('assert'),

    webdriverio = require('webdriverio'),

    client = webdriverio.remote({

        desiredCapabilities: {

            browserName: 'chrome'

        }

    });



describe('Google', function () {

    this.timeout(5000);



    beforeEach(function (done) {

        client

            .init()

            .url('http://google.com')

            .call(done);

    });



    it('проверяет заголовок', function (done) {

        client

            .getTitle(function (error, title) {

                assert.equal(title, 'Google');

            })

            .call(done);

    });



    afterEach(function (done) {

        client

            .end()

            .call(done);

    });

});

Разберем код более подробнее.
Вызовом webdriverio.remote мы создаем экземпляр клиентского API для управления браузером Chrome. Использование браузера chrome в коде указывается явно - по-умолчанию WebdriverIO привык работать с Firefox.
Вызовом this.timeout(5000) устанавливаем лимит ожидания Mocha в 5 сек на отдельную операцию внутри тестого кейса, например, открытие и загрузку страницы Google.com. Заметим, что установив эту настройку на небольшую величину, можно требовать определенный уровень скорости работы вашего веб-приложения.

Хуки beforeEach и afterEach запускают в браузере страницу Google.com и закрывают его соответственно перед и после выполнения каждого тестового кейса it.

Стоит отметить, что асинхронное API на основе Promise является отличительной особенностью использования WebdriverIO со сторонними тест-раннерами сравнению с wdio (как мы увидим ниже).

WebdriverIO + wdio testrunner

По аналогии, установим библиотеки, необходимые для организации тестирования на базе WebdriverIO + wdio

npm install —save-dev gulp
npm install —save-dev selenium-standalone
npm install —save-dev webdriverio
nom-install —save-dev assert

Для запуска заданий WebdriverIO при помощи gulp установим соответствующий адаптер (https://www.npmjs.com/package/gulp-webdriver):

npm install —save-dev gulp-webdriver

В качестве библиотеки для описаний тестов мы снова будем использовать Mocha, поэтому нам потребуется соответствующий plugin WebdriverIO (https://www.npmjs.com/package/wdio-mocha-framework):

npm install —save-dev wdio-mocha-framework

И на этот раз наш gulpfile.js будет содержать три таска:

var gulp = require('gulp'),

    webdriver = require('gulp-webdriver'),

    selenium = require('selenium-standalone');



gulp.task('selenium', function (done) {

    selenium.install(

        {

            logger: function (message) {

                console.log(message);

            }

        },

        function (error) {

            if (error) return done(error);


            selenium.start(function (error, child) {

                if (error) return done(error);

                selenium.child = child;

                done();

            });

        }

    );

});



gulp.task('wdio', ['selenium'], function() {

    return gulp.src('wdio.conf.js').pipe(webdriver());

});



gulp.task('test', ['wdio'], function () {

    selenium.child.kill();

});

Запуск Mocha заменен на запуск wdio с файлом конфигурации wdio.conf.js, пример которого можно взять с соответствующей страницы сайта WebdriverIO. Здесь я приведу только те настройки, которые повлияют на запуск нашего примера:

specs: [

    'tests/**/*Test.js'

],
capabilities: [{

    browserName: 'chrome'

}],
waitforTimeout: 10000,
framework: 'mocha’

Как и прежде, мы будем брать тесты из папки tests, использовать браузер Chrome, библиотеку для описания тестов Mocha, а лимит на исполнение отдельных операций повысим до 10 секунд.

Содержимое файла tests/ExampleTest.js теперь будет выглядеть так:

var assert = require('assert');



describe('Google', function () {

    this.timeout(5000);



    beforeEach(function (done) {

        browser.url('http://google.com');

        browser.call(done);

    });



    it('проверяет заголовок', function () {

        assert(browser.getTitle(), 'Google');

    });

});

Как видно из кода примера исчез код, отвечающий за настройку клиента WebdriverIO. Все соответствующие операции wdio выполняет под капотом и наружу предоставляет клиентское API в виде глобального объекта browser. API wdio носит синхронный характер, что очень удобно для тех, кто не чувствует себя уверенным при работе с Promise.

Очевидно, что код, описывающий тесты с использованием wdio отличается краткостью и отсутствием рутинных настроек, что является большим плюсом в пользу использования wdio. Единственным принципиальным недостатком при использовании wdio на сегодняшний день является его слабая поддержка ключевыми IDE, например, тесты на Mocha могут быть запущены для отладки непосредственно c использованием интерфейсных возможностей IDE, чего о wdio сказать нельзя. Однако, Как показывает практика, раннер wdio отвечает своему назначению и имеет право на существование.

Полный исходный код примеров доступен в репозитории GitHub https://github.com/ivan-bausov/webdriverio-study.

Итак, мы рассмотрели запуск автоматизированных тестов веб-интерфейса с использованием API WebdriverIO в связке с раннерами Mocha и wdio и построили простейший процесс запуска тестов с использованием Gulp.

by 18.04.2016