Проводя автотесты для скорости и надежности тестирования, в разработке и процессах 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), например, ночью. Город засыпает, тесты просыпаются, а утром команда получает отчеты по сотням и тысячам проведенных проверок.
Спасибо за внимание! Надеемся, что наш опыт был вам полезен.