[PHP] Ускоряем и стабилизируем автотесты на codeception + selenium
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Как прогнать несколько часов автотестов за 5 минут и при этом, чтобы это было стабильно и не вызывало головной боли при каждой сборке? Без лишней воды и вступлений предоставляю вашему внимаю сборник костылей и подпорок элегантных архитектурных решений, без которых невозможно добиться высокой скорости и стабильности автотестов.
Входные данные: фреймворк codeception, сервер с selenium, код на PHP, который нужно протестировать.
Кратко перечислю сборник элегантных архитектурных решений, а затем остановимся на каждом из них подробнее.
- Первое и самое очевидное — это запараллеливание выполнения тестов, точнее запуск в несколько потоков групп тестов.
- Заполнение полей форм с помощью javascript.
- Далее на третьем месте по списку, но не по значимости стоит такое явление как перезапуск только тех тестов, которые упали, а не всего набора тестов.
- Перезапуск сессии с selenium.
- Очистка контекста в браузерных тестах
- Перезапуск потока.
Теперь подробнее про каждый пункт.
Параллельный запуск
В codeception есть возможность поделить тесты на группы с помощью нотации @ group в phpdoc метода или же всего класса. После распределения таким образом тесты на группы происходит их запуск в отдельном процессе, с помощью https://robo.li/.
Как выполнить этот запуск смотрим тут https://robo.li/tasks/Testing/#codecept.
Небольшая подсказка: group($group) set group option. Can be called multiple times.
Сколько делать одновременных потоков — каждый сам должен понять, все зависит от ресурсов сервера, на котором крутятся тесты. На нашем проекте может одновременно крутиться десятки потоков.
Нужно не забыть перезапускать упавшие тесты также в несколько потоков. Если этого не делать, то будет ситуация когда прогон тестов из 10 потоков прошедший за 5 минут будет ждать перезапуска, например, 3 тестов, которые в один поток могут выполняться больше минуты.
Заполнение форм через Javascript
В какой-то момент выяснилось, что заполнение полей форм, а в тестах приходится много заполнять полей всяких разных форм, занимает очень много времени и чтобы сэкономить драгоценное время применена заплатка в виде заполнения поля на javascript.
Мы переписали метод fillField библиотеки codeception.
Собственно вот часть кода, отражающая, суть:
$webDriver->executeJS(
‘element = document.querySelector(arguments[0]);
element.value = arguments[1]’,
[$selector, $value])
Сами причины почему selenium долго заполняет поля текстом не ясны, к сожалению
Перезапуск упавших тестов
Это настолько очевидное и банальное казалось бы, но в самом фреймворке нет такой возможности, на то он и фреймворк как говорится, пусть люди сами делают что хотят.
Кто то скажет, что перезапуск тестов это зло и что вы все неправильно делаете, но реальность такова, что тесты все же падают, и довольно часто. И мы просто смирились с этим и адаптировались к этому.
Перезапуск перезапуску рознь, во-первых каждое падение и перезапуск должно фиксироваться с максимально возможным количеством сопутствующих данных, чтобы разработчик мог оценить и понять причину падений.
Во-вторых нужно иметь под рукой список тестов отсортированных по количеству падений, чтобы понимать над каким тестом стоит провести исправительную работу.
Перезапуск должен быть только тех тестов которые упали — то что не упало не перезапускаем, чтобы не тратить время. Тесты не связаны между собой и запуск одного отдельного теста не должен вызывать проблем.
Перезапуск сессии с selenium
Когда у вас запущено много потоков, а сервер с selenium один и он уставший, может проскальзывать ошибка под названием «Session timed out or not found», и тут нам помогает перезапуск сессии с selenium.
Вот код который делает перезапуск сессии:
/** @var WebDriver $webDriver */
$webDriver = $I->getWebDriver();
try {
$I->amOnPage('/robots.txt');
} catch (\Facebook\WebDriver\Exception\WebDriverException $e) {
try {
$I->comment('Что-то с сессией в селениуме - пытаюсь перезапустить сессию');
$webDriver->debugWebDriverLogs();
$webDriver->_restart();
} catch (\Throwable $e) {
$I->comment('Омайгад перезапустить не удалось, просто создаю новую сессию');
$webDriver->_initializeSession();
}
$I->amOnPage('/robots.txt');
}
robots.txt это текстовой файл находящийся на домене который будет тестироваться, запрос на него нужен, чтобы точно знать, что сессия в браузере рабочая и можно начать выполнение теста, этот блок кода должен выполняться перед каждым тестом.
Подробнее про текстовой файл будет в следующем пункте.
Очистка контекста в браузерных тестах
Чтобы очистить контекст текущей сессии браузера в selenium нужно сделать запрос на любую другую страницу, чтобы поменялась структура документа. Чтобы не нагружать серверы ненужным рендерингом, запрос делается на любой текстовой файл, и так сложилось, что этим файлом у нас стал robots.txt.
Собственно зачем делать эту так называемую очистку контекста? Она нужна для того, чтобы тесты не смогли использовать разметку страницы из предыдущего теста. Часто бывало такое, что браузер находил элементы, которых нет на текущей странице или же, наоборот, не находил то, что нужно было найти и падал с ошибкой. Это происходит из-за того, что сценарий тестов на PHP не дожидается загрузки новой страницы и начинает делать всякие seeElement, waitForText в уже имеющейся(старой) структуре документа и в результате мы не понимаем, что произошло и почему упал тест. И тут то нас спасает предварительный запрос на robots.txt, после него мы имеем чистое место для начала нового тестового сценария.
Перезапуск потока
Проблемы с запуском и прохождением тестов могут быть не только на стороне сервера selenium (вот это неожиданность), но и на исполняющей стороне, там где запущен php процесс, обычно это CI сервер.
Так как на CI сервере происходит очень много всего, то по разным причинам php процессы, внезапно, могут обрываться и тем самым у нас получится что целая группа тестов останется не пройденной и придется ждать ее отдельного перезапуска. Тут к нам спешат на помощь Чип и Дейл проверка состояния процесса и его перезапуск если он вдруг завершится.
Чтобы сделать перезапуск процесса пришлось переопределить метод \Robo\Task\Base\ParallelExec::run
Вот отрывок кода:
if (!$process->isRunning()) {
$doRerun = $this->doRerunCallback;
$nbRerun = $nbRerunForProcess[$process->getCommandLine()] ?? 0;
if ($doRerun($process) && $nbRerun <= 3) {
$this->printTaskInfo(
'Try to rerun ' . $nbRerun . ' time ' .
" for {command}: \n\n{output} \nend output for rerun",
[
'command' => $process->getCommandLine(),
'output' => $process->getOutput(),
'_style' => ['command' => 'fg=white;bg=magenta'],
]
);
$nbRerun++;
$nbRerunForProcess[$process->getCommandLine()] = $nbRerun;
$process->start();
} else {
В этом методе уже есть проверка состояния процесса и нам нужно дописать десяток строк, чтобы этот процесс перезапускался по какому то условию, условие лежит в $this->doRerunCallback, это функция обратного вызова, в которой мы определяем нужно ли делать перезапуск. В ней у нас лежит следующее:
$parallel->setDoRerunCallback(function (Process $process) use ($self) {
$group = $self->getGroupFromCmd($process->getCommandLine());
if ($group) {
return !$self->checkGroupReportExist($group);
}
return false;
});
Т.е. по сути там проверка есть ли отчет по данной группе тестов или нет.
Итог
Кто уже сталкивался с браузерными тестами или вообще с автотестированием, наверное, знают из каких костылей и подпорок могут состоять эти системы. Я представил большую часть подпорок со стороны кода.
Как видно, большой упор делается на автоматический перезапуск, и если сборка упала, то с высокой долей вероятности это ошибка в коде и нужно смотреть на упавший тест.
===========
Источник:
habr.com
===========
Похожие новости:
- [CMS, PHP, Программирование, Разработка под e-commerce, Интернет-маркетинг] Генератор ocmod-файла для интернет-магазина на Opencart
- [PHP, API, Тестирование веб-сервисов, Тестирование мобильных приложений] API для QA: тестируем фичи без доступа к коду
- [PHP, Разработка под e-commerce, Magento] Очереди на очереди: Magento 2 + RabbitMQ
- [PHP, Yii] Новости Yii 2020, выпуск 7
- [Open source, PHP, Программирование, Компиляторы] ВКонтакте снова выкладывает KPHP
- [PHP, Программирование, Laravel] Печатные формы документов для Eloquent в 0 строчек кода
- [PHP, Управление сообществом, Карьера в IT-индустрии, Конференции] Полезные привычки программиста после 30, MySQL vs Postgres и как поговорить об этом в субботу
- [PHP, SQL] Как я решил написать ORM на php с нуля на работающем сайте, и что из этого вышло
- [Разработка веб-сайтов, PHP, Laravel] Laravel–Дайджест (2–8 ноября 2020)
- [Поисковые технологии, PHP, MySQL, JavaScript, Функциональное программирование] Pick — самая маленькая поисковая система на PHP и MySQL
Теги для поиска: #_php, #_codeception, #_selenium, #_php
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 18:39
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Как прогнать несколько часов автотестов за 5 минут и при этом, чтобы это было стабильно и не вызывало головной боли при каждой сборке? Без лишней воды и вступлений предоставляю вашему внимаю сборник костылей и подпорок элегантных архитектурных решений, без которых невозможно добиться высокой скорости и стабильности автотестов. Входные данные: фреймворк codeception, сервер с selenium, код на PHP, который нужно протестировать. Кратко перечислю сборник элегантных архитектурных решений, а затем остановимся на каждом из них подробнее.
Теперь подробнее про каждый пункт. Параллельный запуск В codeception есть возможность поделить тесты на группы с помощью нотации @ group в phpdoc метода или же всего класса. После распределения таким образом тесты на группы происходит их запуск в отдельном процессе, с помощью https://robo.li/. Как выполнить этот запуск смотрим тут https://robo.li/tasks/Testing/#codecept. Небольшая подсказка: group($group) set group option. Can be called multiple times. Сколько делать одновременных потоков — каждый сам должен понять, все зависит от ресурсов сервера, на котором крутятся тесты. На нашем проекте может одновременно крутиться десятки потоков. Нужно не забыть перезапускать упавшие тесты также в несколько потоков. Если этого не делать, то будет ситуация когда прогон тестов из 10 потоков прошедший за 5 минут будет ждать перезапуска, например, 3 тестов, которые в один поток могут выполняться больше минуты. Заполнение форм через Javascript В какой-то момент выяснилось, что заполнение полей форм, а в тестах приходится много заполнять полей всяких разных форм, занимает очень много времени и чтобы сэкономить драгоценное время применена заплатка в виде заполнения поля на javascript. Мы переписали метод fillField библиотеки codeception. Собственно вот часть кода, отражающая, суть: $webDriver->executeJS(
‘element = document.querySelector(arguments[0]); element.value = arguments[1]’, [$selector, $value]) Сами причины почему selenium долго заполняет поля текстом не ясны, к сожалению Перезапуск упавших тестов Это настолько очевидное и банальное казалось бы, но в самом фреймворке нет такой возможности, на то он и фреймворк как говорится, пусть люди сами делают что хотят. Кто то скажет, что перезапуск тестов это зло и что вы все неправильно делаете, но реальность такова, что тесты все же падают, и довольно часто. И мы просто смирились с этим и адаптировались к этому. Перезапуск перезапуску рознь, во-первых каждое падение и перезапуск должно фиксироваться с максимально возможным количеством сопутствующих данных, чтобы разработчик мог оценить и понять причину падений. Во-вторых нужно иметь под рукой список тестов отсортированных по количеству падений, чтобы понимать над каким тестом стоит провести исправительную работу. Перезапуск должен быть только тех тестов которые упали — то что не упало не перезапускаем, чтобы не тратить время. Тесты не связаны между собой и запуск одного отдельного теста не должен вызывать проблем. Перезапуск сессии с selenium Когда у вас запущено много потоков, а сервер с selenium один и он уставший, может проскальзывать ошибка под названием «Session timed out or not found», и тут нам помогает перезапуск сессии с selenium. Вот код который делает перезапуск сессии: /** @var WebDriver $webDriver */
$webDriver = $I->getWebDriver(); try { $I->amOnPage('/robots.txt'); } catch (\Facebook\WebDriver\Exception\WebDriverException $e) { try { $I->comment('Что-то с сессией в селениуме - пытаюсь перезапустить сессию'); $webDriver->debugWebDriverLogs(); $webDriver->_restart(); } catch (\Throwable $e) { $I->comment('Омайгад перезапустить не удалось, просто создаю новую сессию'); $webDriver->_initializeSession(); } $I->amOnPage('/robots.txt'); } robots.txt это текстовой файл находящийся на домене который будет тестироваться, запрос на него нужен, чтобы точно знать, что сессия в браузере рабочая и можно начать выполнение теста, этот блок кода должен выполняться перед каждым тестом. Подробнее про текстовой файл будет в следующем пункте. Очистка контекста в браузерных тестах Чтобы очистить контекст текущей сессии браузера в selenium нужно сделать запрос на любую другую страницу, чтобы поменялась структура документа. Чтобы не нагружать серверы ненужным рендерингом, запрос делается на любой текстовой файл, и так сложилось, что этим файлом у нас стал robots.txt. Собственно зачем делать эту так называемую очистку контекста? Она нужна для того, чтобы тесты не смогли использовать разметку страницы из предыдущего теста. Часто бывало такое, что браузер находил элементы, которых нет на текущей странице или же, наоборот, не находил то, что нужно было найти и падал с ошибкой. Это происходит из-за того, что сценарий тестов на PHP не дожидается загрузки новой страницы и начинает делать всякие seeElement, waitForText в уже имеющейся(старой) структуре документа и в результате мы не понимаем, что произошло и почему упал тест. И тут то нас спасает предварительный запрос на robots.txt, после него мы имеем чистое место для начала нового тестового сценария. Перезапуск потока Проблемы с запуском и прохождением тестов могут быть не только на стороне сервера selenium (вот это неожиданность), но и на исполняющей стороне, там где запущен php процесс, обычно это CI сервер. Так как на CI сервере происходит очень много всего, то по разным причинам php процессы, внезапно, могут обрываться и тем самым у нас получится что целая группа тестов останется не пройденной и придется ждать ее отдельного перезапуска. Тут к нам спешат на помощь Чип и Дейл проверка состояния процесса и его перезапуск если он вдруг завершится. Чтобы сделать перезапуск процесса пришлось переопределить метод \Robo\Task\Base\ParallelExec::run Вот отрывок кода: if (!$process->isRunning()) {
$doRerun = $this->doRerunCallback; $nbRerun = $nbRerunForProcess[$process->getCommandLine()] ?? 0; if ($doRerun($process) && $nbRerun <= 3) { $this->printTaskInfo( 'Try to rerun ' . $nbRerun . ' time ' . " for {command}: \n\n{output} \nend output for rerun", [ 'command' => $process->getCommandLine(), 'output' => $process->getOutput(), '_style' => ['command' => 'fg=white;bg=magenta'], ] ); $nbRerun++; $nbRerunForProcess[$process->getCommandLine()] = $nbRerun; $process->start(); } else { В этом методе уже есть проверка состояния процесса и нам нужно дописать десяток строк, чтобы этот процесс перезапускался по какому то условию, условие лежит в $this->doRerunCallback, это функция обратного вызова, в которой мы определяем нужно ли делать перезапуск. В ней у нас лежит следующее: $parallel->setDoRerunCallback(function (Process $process) use ($self) {
$group = $self->getGroupFromCmd($process->getCommandLine()); if ($group) { return !$self->checkGroupReportExist($group); } return false; }); Т.е. по сути там проверка есть ли отчет по данной группе тестов или нет. Итог Кто уже сталкивался с браузерными тестами или вообще с автотестированием, наверное, знают из каких костылей и подпорок могут состоять эти системы. Я представил большую часть подпорок со стороны кода. Как видно, большой упор делается на автоматический перезапуск, и если сборка упала, то с высокой долей вероятности это ошибка в коде и нужно смотреть на упавший тест. =========== Источник: habr.com =========== Похожие новости:
|
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 18:39
Часовой пояс: UTC + 5