Перейти к основному содержимому

Как обновить hermione до версии 4.x

warning

Данный рецепт актуален только для тех проектов, которые используют hermione младше 4-й версии.

Почему стоит обновиться?

Когда-то очень давно hermione перешла на «временный» форк пакета webdriverio@4 (сокр. wdio), который она использовала «под капотом», т. к. проблемы во внешнем wdio тормозили её разработку: постоянные баги в wdio, разногласия относительно вносимых изменений и т. п. И если сначала форк регулярно обновлялся командой hermione, чтобы предоставить пользователю актуальную функциональность, то со временем форк значительно отстал от текущей версии wdio во внешнем мире.

К тому времени во внешнем мире в wdio уже появилось много различных фич, которые интересны разработчикам: Chrome DevTools Protocol (CDP), стабы внешних запросов, расширенные возможности работы с мобильными устройствами и т. п. Поэтому у команды hermione не осталось выбора: нужно было отказываться от форка webdriverio@4 и переходить на самую актуальную версию webdriverio@7.

к сведению

Сейчас уже доступна 8-я версия webdriverio и hermione@7 уже использует её.

Кроме этого, пользователям становилось всё неудобнее пользоваться устаревшими командами: тайпинги приходилось подключать из отдельного пакета (в новом wdio они поставляются из коробки), за документацией по командам приходилось ходить на старый сайт, в то время как некоторые пользователи иногда заходили на актуальную страницу и не могли понять, почему команды из документации не работают в hermione.

Таким образом, причин для радикального апгрейда — сразу на 3 мажора вверх — накопилось достаточно.

Что изменилось?

Изменений очень много, поэтому ниже будут перечислены только самые важные / интересные из них.

API команд

async/await вместо чейнинга

В новой версии теперь нельзя писать тесты, используя chaining. Доступен только async/await-синтаксис:

  it('some test', function() {
return this.browser
.foo()
.bar()
.baz();
});

А начиная с версии hermione@4.9.0 можно писать тесты ещё короче, так как hermione теперь передает в функцию объект с полем browser:

it("some test", async function ({ browser }) {
await browser.foo();
await browser.bar();
await browser.baz();
});
warning

Далее в примерах «Стало» мы будем везде предполагать, что речь идет о hermione с версией не меньше, чем 4.9.0. Если по какой-то причине вы планируете использовать версию hermione 4+ младше 4.9.0, то к браузеру в тестах нужно обращаться как и раньше — через this, например: await this.browser.getText('.selector').

Результат вместо объекта с ключом value

Теперь при получении результатов команд вместо объекта с ключом value возвращается реальный результат (старое поведение часто приводило к ошибкам в тестах):

  it('some test', async function() {
const { value } = await this.browser.getText('.selector');
console.log(value); // some text
});

Работа с элементами напрямую

С помощью команды browser.$ можно получить инстанс найденного элемента и работать с ним в тесте. Это удобно, когда с элементом нужно взаимодействовать больше одного раза (при этом элемент не будет повторно искаться на странице):

  it('some test', async function() {
await this.browser.clearElement('.input');
await this.browser.setValue('.input', 'text');
});

Смотрите также команды:

Передача аргументов через объект

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

it('some test', async function() {
await this.browser.waitForExist('.selector', 1000, true);
});

Специальная команда для React

Бонус для тех, кто уже перешел на React — теперь в тестах можно использовать команды browser.react$ и browser.react$$ для поиска на странице конкретных react-компонентов с определенными состояниями. Аналогичные команды есть и для элементов — element.react$ и element.react$$.

Также читайте статью о вариантах работы с react-компонентами на сайте webdriverio.

Пример использования:

it('some test', async function() {
// специальных команд для работы с react-компонентами – нет :(
});

Актуальная документация

Пока hermione использовала старую версию webdriverio@4, приходилось все время уточнять, что документация на все команды лежит по отдельному адресу: v4.webdriver.io/api.html. Теперь же описания всех команд webdriverio, которые используются hermione, можно найти по стандартному адресу: webdriver.io/docs/api.

Помимо этого, мы перевели описания всех команд на русский язык и адаптировали все примеры использования этих команд под hermione, так как в webdriverio свой раннер и примеры в его документации неприменимы напрямую в hermione.

Тесты выполняются быстрее

При локальных прогонах нескольких тестов вы, скорее всего, этого ускорения не заметите, но на большом количестве тестов это будет весьма ощутимо. Новые команды работают быстрее примерно на 15% (при условии, что вы отказались от использования старых команд).

Простой запуск тестов на локальном браузере

Раньше для того, чтобы запустить тесты локально на своем браузере, нужно было запустить selenium-standalone и указать hermione магический gridUrl, чтобы все заработало. Сейчас же — достаточно в конфиге указать браузеру опцию automationProtocol со значением devtools:

// hermione.conf.js
module.exports = {
browsers: {
chrome: {
automationProtocol: 'devtools',
desiredCapabilities: {
// ...
}
}
},

// другие настройки hermione...
};

Также мы планируем добавить отдельную кнопку в hermione GUI для перехода в CDP-режим, чтобы было еще проще.

warning
  • На данный момент это полноценно поддержано только в браузере Chrome. * Переснимать скриншоты в таком режиме можно только для дебага, т. к. в конвейере браузеры запускаются под Linux, соответственно: рендеринг страницы будет отличаться и в пулл-реквесте тесты упадут с диффом.

API для стаба походов по сети

В новой версии доступна возможность застабать ответы вашего сервиса или переопределить их. Делается это с помощью команды mock.respond(). Также можно запрещать походы по урлам внешних сервисов.

Более подробно о всех возможностях читайте в рецепте «Как отслеживать и перехватывать сетевые запросы и ответы».

warning

На данный момент эта функциональность работает только в режиме Chrome DevTools Protocol (CDP), который работает только в Chrome и Firefox Nightly.

Конфигурация браузеров в конфиге

Для браузеров, поддерживающих работу W3C-протокола, вместо поля version нужно указывать browserVersion. А для дополнительных опций нужно добавлять префикс браузера:

  module.exports = {
browsers: {
'chrome-desktop': {
desiredCapabilities: {
browserName: 'chrome',
version: '75',
'chromeOptions': {
// ...
}
}
}
}
};

Подробнее про вендорные префиксы читайте по ссылке.

Список всех доступных настроек можно посмотреть в спецификации.

Как переехать?

Мы обновились сразу на 3 мажора webdriverio, поэтому просто обновить версию hermione в package.json не получится. Основные проблемы при переезде — это отсутствующий chaining в тестах и устаревшие команды тестов. Чтобы вам было проще разобраться с обеими проблемами, мы написали для вас следующую инструкцию.

1. Обновите hermione до 4+, установите плагин мигратора и кодмод

А именно:

  • обновите версию hermione до hermione@4;
  • установите плагин hermione-wdio-migrator для плавной миграции команд;
  • установите пакет hermione-codemod для конвертации существующих тестов в новый синтаксис;

Всё это вы можете сделать одной командой:

npm install -D hermione@4 hermione-wdio-migrator hermione-codemod --save-exact

Версии всех плагинов hermione (например, html-reporter) также необходимо обновить до последних версий, т. к. часть из них может работать неправильно с новой версией hermione.

2. Запустите кодмод на async/await

Кодмод перегенерит ваши тесты с chaining-формата в формат async/await:

Если вы используете командный процессор zsh, то файлы тестов можно передавать не только в виде относительных путей, но и в виде глобов, например: somefolder/**/*.js и т. п.

npx jscodeshift -t node_modules/hermione-codemod/transforms/browser-chaining-to-async-await.js path_to_file_mask

При успешном завершении вы увидите соответствующее сообщение:

Results:
0 errors
0 unmodified
0 skipped
251 ok

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

WARN: can't correctly transform ConditionalExpression, fix it manually
file: tests/hermione/suites/common/promotion-page/promotion-page.hermione.js
position: {"start":112,"end":116}

Такие тесты придется править руками. Мы старались учесть большинство тестов, поэтому таких случаев должно быть не очень много.

После этого вы уже можете вливать свои изменения (это не обязательно), чтобы выполнять переезд по частям. Дело в том, что в wdio@4 синтаксис async/await тоже будет работать. Т. е. вы всегда могли писать тесты таким образом (а некоторые сервисы уже давно так и делали).

3. Запустите кодмод на удаление value

Так как теперь при получении результатов команд вместо объекта с ключом value возвращается реальный результат, нужно изменить во всех тестах сохранение результата. Следующий кодмод предназначен именно для этого случая.

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

npx jscodeshift -t node_modules/hermione-codemod/transforms/remove-browser-prop.js path_to_file_mask

При наличии ворнингов проблемные тесты нужно будет исправить вручную. Например, если в рамках одного теста есть многократное использование value через деструктуризацию, то кодмод с таким не справится и в коде теста получится несколько переменных с одним именем. Например:

// тест на wdio@4:
it('test', function(){
return this.browser
...
.getText('.button')
.then((value) => {
assert.equal(value, 'Кнопка', 'Нам нужна кнопка');
})
...
.getValue('.input')
.then((value) => {
assert.equal(value, 'Привет', 'С нами не поздоровались');
});
});

// перегенерится для wdio@7 в такой формат:
it('test', async function() {
const value = await this.browser.getText('.button');
assert.equal(value, 'Кнопка', 'Нам нужна кнопка');
...
// здесь будет ошибка из-за повторного использования названия переменной,
// поэтому кодмод выдаст ворнинг о проблемном месте
const value = await this.browser.getValue('.input');
assert.equal(value, 'Привет', 'С нами не поздоровались');
});

Если при запуске кодмодов в вашем проекте оказалось слишком много тестов, которые не поддаются автоматической миграции, то обратитесь, пожалуйста, в github issues за помощью. Мы проанализируем эти ошибки и поможем с переездом.

4. Добавьте hermione-wdio-migrator в конфиг hermione

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

module.exports = {
plugins: {
"hermione-wdio-migrator": {
enabled: true,
},

// остальные плагины hermione...
},

// другие настройки hermione...
};

5. Удалите кодмод

Пакет hermione-codemod нужно деинсталлировать, т. к. в дальнейшем он не понадобится.

npm uninstall hermione-codemod

6. Запустите линтеры

Нужно запустить линтеры на измененные тесты, т. к. кодмод мог нарушить правила написания кода в вашем проекте.

7. Запустите тесты

На последнем шаге нужно убедиться, что все тесты успешно проходят, например, создав пулл-реквест и проверив, что все тесты успешно выполнились в CI.

Заключение

Обновление webdriverio принесло много полезных вещей. Некоторыми можно пользоваться уже сейчас, некоторые в более удобном виде появятся чуть позже. Поэтому, мы крайне настоятельно рекомендуем переезжать на новую версию, чтобы написание тестов стало более удобным, быстрым и приятным.

warning

Старая версия hermione находится в режиме ограниченной поддержки и новые фичи в ней появляться не будут.

Поддержка

Если при переезде на новую версию вы столкнетесь с проблемами, или у вас возникнут какие-либо вопросы, то приходите в github issues — и мы обязательно вам поможем!