Проводя автотесты для скорости и надежности тестирования, в разработке и процессах CI/CD зачастую используют следующий стек технологий – Jenkins, Selenoid и Allure. Можно выделить несколько их преимуществ: у Jenkins это бесплатный доступ, большое количество возможностей и плагинов для расширения; у Selenoid – независимость окружений, каждый браузер запускается в отдельном контейнере; Allure, в свою очередь, в последние годы стал популярным инструментом для построения отчетов по результатам автотестов (подробнее об этом мы писали в прошлой статье). При этом информации о том, как эти инструменты можно сочетать, до сих пор достаточно мало, и мы хотим поделиться своим примером.

Ранее мы уже писали о задачах автоматизации тестирования и возможных проверках. В этой статье рассмотрим процессы построения пайплайна для Jenkins и настройку билда. Для реализации этой задачи нам понадобится следующее:
Установленный Jenkins (мы использовали Jenkins на локальной машине с Ubuntu 20.04).
Работающий локально проект на Python, в котором в requirements.txt прописаны все необходимые зависимости, подключён Allure и присутствуют автотесты с добавленными аннотациями. Например,
@allure.title("Позитивный тест расчёта")
или@allure.step("Заполнить поле {locator_name} текстом {text}")
. С помощью этого мы получим “волшебство" в Allure – отчет со всеми деталями тестов.Проект должен быть залит в репозиторий (в нашем случае GitHub).
Установленный Docker и Docker Compose.
Если ваш Jenkins не “подружился” с Docker, вы можете узнать об этом в логах после сборки билда. Вам потребуется добавить Jenkins в группу Docker – в частности, на Ubuntu это делается так: sudo usermod -a -G docker jenkins
На этом можно считать, что база готова. Приступаем к настройке самого пайплайна.
Как выглядит структура описанного проекта:
/pages
страница для описания локаторов
базовая страница POM
страница с действиями и проверками в тесте
data.py
Dockerfile
Jenkinsfile
browsers.json
conftest.py
pytest.ini
requirements.txt
test_main_page.py
Настройки запуска сборки в Jenkins
Далее приведем пример настроек. Сразу уточним, что мы использовали Jenkins на русском, но его локализация полностью не завершена, поэтому отдельные примеры даны на английском:
Нажимаем “New Item”, вводим название, выбираем Pipeline – Ок.
Ставим галочку напротив “Do not allow concurrent builds”, чтобы один билд дожидался выполнения другого.
Выбираем “Удалять устаревшие сборки”. Указываем, сколько последних сборок надо хранить (в нашем примере 5).
Выбираем параметризованную сборку, нажимаем "Добавить параметр" – String Parameter – и далее:
В поле “Имя” вводим переменную CMD_PARAMS.
В значении по умолчанию указываем путь к тестам, которые хотим прогнать. У нас это test_main_page.py
В описании вы можете добавить комментарии о том, какие возможности есть у сборки.
Эти действия будут полезны при запуске сборок, позволят менять флаги запуска и подаваемые в работу тесты.

Переходим к заполнению Pipeline в настройках. Выбираем “Pipeline script from SCM”.
В качестве SCM выбран Git. Заполняем “Repository URL”, нажимаем “Add Credentials”, чтобы ввести логин и пароль для гита. Прописываем ветку, с которой необходимо забирать код, в нашем случае это */master. Просмотрщик репозитория – автоматически.
“Script Path” – Jenkinsfile, который лежит у нас в корне проекта.

Нажимаем кнопку «Сохранить», и настройки готовы.

Добавление Allure Plugin
После установки Allure plugin переходим в Dashboard Jenkins > настройки Jenkins > Конфигурация глобальных установок > Allure Commandline в конце списка.
Конфигурирование Jenkinsfile
Теперь переходим к Jenkinsfile и самому пайплайну.
pipeline {
agent any
stages {
stage("Build image") {
steps {
catchError {
script {
docker.build("python-web-tests", "-f Dockerfile .")
}
}
}
}
stage('Pull browser') {
steps {
catchError {
script {
docker.image('selenoid/chrome:92.0')
}
}
}
}
stage('Run tests') {
steps {
catchError {
script {
docker.image('aerokube/selenoid:1.10.4').withRun('-p 4444:4444 -v /run/docker.sock:/var/run/docker.sock -v $PWD:/etc/selenoid/',
'-timeout 600s -limit 2') { c ->
docker.image('python-web-tests').inside("--link ${c.id}:selenoid") {
sh "pytest -n 2 --reruns 1 ${CMD_PARAMS}"
}
}
}
}
}
}
stage('Reports') {
steps {
allure([
includeProperties: false,
jdk: '',
properties: [],
reportBuildPolicy: 'ALWAYS',
results: [[path: 'report']]
])
}
}
}
}
Пайплайн разделен на этапы stage, в которых выполняются следующие действия:
stage("Build image") – здесь собираем контейнер с нашими тестами (что происходит в Dockerfile, опишем отдельно).
stage('Pull browser') – на данном этапе поднимаем контейнер с браузером, если он не был скачан ранее, скачиваем.
stage('Run tests') – пожалуй, самый интересный и запутанный этап. Здесь мы скачиваем образ и подключаем контейнер Selenoid, а скрипт -p 4444:4444 -v /run/docker.sock:/var/run/docker.sock -v $PWD:/etc/selenoid/ прокидывает порт 4444 для Selenoid и путь к конфигурации браузера (как вы помните, browsers.json лежит в корне $PWD:/etc/selenoid/). Флаг
-limit 2
указывает на количество запускаемых браузеров, здесь важно помнить, что количество поднимаемых браузеров зависит от мощности машины, рекомендуется 1 CPU + 1 Gb оперативки на один браузер. Про флаги таймаутов подробнее можно почитать тут. Далее запускаем тесты из контейнера, который собрали ранее:И последний этап stage('Reports') – это создание отчета Allure. Здесь нужно указать путь к папке со сгенерированными отчётами, в нашем случае это
path: 'report'
. Этот этап можно пропустить, если вы не используете Allure.
Получение драйвера из Selenoid
Следующий пункт, по которому могут возникнуть вопросы – это установка параметров драйвера для того, чтобы всё работало в Jenkins.
В conftest.py в нашем примере следующая фикстура для получения драйвера:
@pytest.fixture(scope="function")
def browser():
chrome_options = webdriver.ChromeOptions()
browser = webdriver.Remote(
command_executor='http://selenoid:4444/wd/hub',
desired_capabilities={'browserName': 'chrome',
'version': '92.0'},
options=chrome_options)
browser.maximize_window()
yield browser
browser.quit()
Здесь обращаемся к адресу selenoid и порту 4444. Если вы хотите подключить дополнительно Selenoid UI и наблюдать за тем, что происходит в браузере, необходимо передать параметр 'enableVNC': True в desired_capabilities и, конечно, добавить Selenoid UI в пайплайн. Версия браузера в conftest.py должна соответствовать версии в browser.json.
{
"chrome": {
"default": "92.0",
"versions": {
"92.0": {
"image": "selenoid/chrome:92.0",
"port": "4444"
}
}
}
}
Настройка Dockerfile
Dockerfile будет содержать немного инструкций, т.к. проект скромен и не требуется дополнительных слоёв:
FROM python:3.8.12
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
Берём образ Python, копируем наши зависимости, устанавливаем их и копируем наш код.
Сохранение отчета
И небольшой штрих в pytest.ini для того, чтобы отчеты Allure сохранялись в нужной папке:
[pytest]
addopts = --alluredir=report
В настроенном проекте Jenkins нажимаем кнопку «Собрать с параметрами». При этом есть возможность внести в передаваемый параметр путь к тесту, количество потоков -n или количество перезапусков --reruns на случай, если вы измените решение. После этого можно нажать «Собрать» и ждать прогона тестов. Откройте билд прогона тестов, нажмите на его номер и затем откройте Allure-отчёт, где вы можете увидеть результаты прогона и подробное описание тестов.


Если у вас что-то не запустилось, в первую очередь стоит проверить документацию Selenoid, логи в падающем билде Jenkins (и уже после этого, если нужно, поискать другие способы).
Вывод
В приведенном примере можно один раз настроить сборку билдов и получить “комбайн”, чтобы прогонять автотесты на необходимом количестве независимых браузеров. Важно, что провести тесты можно в любое удобное время (см. отдельный пункт в настройках и комментарий по заполнению в Jenkins), например, ночью. Город засыпает, тесты просыпаются, а утром команда получает отчеты по сотням и тысячам проведенных проверок.
Спасибо за внимание! Надеемся, что наш опыт был вам полезен.
Авторские материалы для разработчиков мы также публикуем в наших соцсетях – ВКонтакте и Telegram.