Как стать автором
Обновить
Синимекс
Разработка IT-систем для бизнеса

Jenkins Pipeline для АТ

Уровень сложностиПростой
Время на прочтение10 мин
Количество просмотров4.5K

В данной статье хочу поделиться содержанием pipeline.jenkinsfile с минимальной необходимостью для организации автоматизированного тестирования. Установку, настройку самого Jenkins мы рассматривать не будем, только pipeline и его содержание для АТ.

Автотесты в нашем случае будут написаны с использованием:

  • java

  • maven

  • junit5

  • allure

Бонусом расскажу как сделать запуск сборки по действию в GitLab.

Что мы хотим от Jenkins?

  • Автоматический запуск тестов по расписанию (ночные прогоны регресса)

  • Хранение самого файла с pipeline в репозитории с исходным кодом автотестов

  • Использование переменных, параметров и сredentials

  • Шаги 

    • клонирование репозитория

    • запуск автотестов с возможностью выбора тестового набора (Test Suite)

    • формирование allure-отчета

  • Нотификация на почту о завершении прогона

pipeline.jenkinsfile

И так, сначала сразу результат, а потом посмотрим на него более детально.

pipeline {
    agent {
        node {
            label 'jenkins-vm.company.ru'
        }
    }
    triggers {
            cron('H 7 * * *')
    }
    parameters{
        choice(choices: ['regress', 'smoke'], description: 'Выбор сьюта для запуска', name: 'suiteToRun')
    }
    environment{
        mailRecipients = 'dminakova@cinimex.ru'
        TEST_CREDS = credentials('444444444')
    }
    stages {
        stage('clone repo') {
            steps{
                checkout([$class                           : 'GitSCM', branches: [[name: '*/master']],
                          doGenerateSubmoduleConfigurations: false,
                          extensions                       : [],
                          submoduleCfg                     : [],
                          userRemoteConfigs                : [[credentialsId: '22222222',
                                                               url          :  'https://git.company.ru/java_example.git']]
                          ])
            }
        }
        stage('run tests') {
            steps{
                catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
                    withMaven(jdk: 'JDK 8u172', maven: 'Maven 3.6.3') {
                        sh 'mvn clean install -Dgroups=${suiteToRun}'
                    }
                }
            }
        }
        stage('run allure reports') {
            steps {
                allure([includeProperties: true,
                                      jdk: '',
                               properties: [],
                        reportBuildPolicy: 'ALWAYS',
                                  results: [[path: '**/allure-results']]
                ])
            }
        }
    }
    post {
        always{
            echo 'Pipeline is complete'
            emailext (
            subject: "CMXQA.TESTS Отчет прогона тестов [${env.BUILD_NUMBER}] ",
            body:"""Подробный allure-отчет: "<a href='${env.BUILD_URL}allure/'>${env.JOB_NAME} [${env.BUILD_NUMBER}]</a>"</p>""",
            to: "${env.mailRecipients}"
            )
        }
    }
}

Ссылка на GitHub: https://github.com/DaryaMin/jenkins_pipeline_at/tree/master


Pipeline детально

Рассмотрим pipeline автотестов более детально.

Сборка автотестов чаще всего содержит следующие блоки:

  1. Переменные

  2. Параметры

  3. Credentials

  4. Триггеры сборки

  5. Этапы/stages

  6. Нотификация

  7. Pipeline from SCM


1. Переменные

Pipeline поддерживает объявление переменных, которые можно в нем дальше использовать.

Для этого используется кодовое слово environment. Переменные перечисляются через запятую по принципу ключ = 'значение'.

В дальнейшем вызываются при помощи ${env.<название переменной>}, например: ${env.mailRecipients}

environment {
        allureResults = 'target/allure-results',
        allureReportPolicy = 'ALWAYS',
        mailRecipients = 'test@cinimex.ru, dminakova@cinimex.ru'
    }

к содержанию

2. Параметры

В Pipeline можно указать некие параметры сборки с возможностью выбора при ручном старте сборки и дефолтным значением для автоматического старта по триггеру. Значения параметров могут использоваться как значения параметров самого приложения, например: url стенда, название сьюта для запуска и т.п.

Кодовое слово - parameters.
Параметры имеют тип, название, значение по умолчанию и описание. 
Параметры бывают разных типов:

  1. string

    Поддерживает строчный параметр, например:
    parameters { string(name: 'DEPLOY_ENV', defaultValue: 'staging', description: '') }

  2. text
    Может содержать несколько строк, например:
    parameters { text(name: 'DEPLOY_TEXT', defaultValue: 'One\nTwo\nThree\n', description: '') }

  3. booleanParam
    Параметр принимающий значения истина/ложь, например:
    parameters { booleanParam(name: 'DEBUG_BUILD', defaultValue: true, description: '') }

  4. choice
    Параметр, который содержит уже конкретные значения к выбору. Часто используется для выбора сьюта (регресс, смок, дебаг), т.к. названия сьютов редко меняются.
    parameters { choice(name: 'CHOICES', choices: ['one', 'two', 'three'], description: '') }

  5. password
    Параметр предназначенный для пароля.
    parameters { password(name: 'PASSWORD', defaultValue: 'SECRET', description: 'A secret password') 

  6. отдельным типом заслуживающим особенного внимания является gitParameter. Этот тип не входит в базовую версию Jenkins и добавляется плагином Git Parametr. parameters { gitParameter(name: 'BRANCH', defaultValue: 'develop', description: 'Ветка, из которой деплоимся', branchFilter: 'origin/(.*)', type: 'PT_BRANCH', selectedValue: 'DEFAULT')}

Пример синтаксиса параметров:
pipeline {
    agent any
    parameters {
        string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?')

        text(name: 'BIOGRAPHY', defaultValue: '', description: 'Enter some information about the person')

        booleanParam(name: 'TOGGLE', defaultValue: true, description: 'Toggle this value')

        choice(name: 'CHOICE', choices: ['One', 'Two', 'Three'], description: 'Pick something')

        password(name: 'PASSWORD', defaultValue: 'SECRET', description: 'Enter a password')
    }
    stages {
        stage('Example') {
            steps {
                echo "Hello ${params.PERSON}"

                echo "Biography: ${params.BIOGRAPHY}"

                echo "Toggle: ${params.TOGGLE}"

                echo "Choice: ${params.CHOICE}"

                echo "Password: ${params.PASSWORD}"
            }
        }
    }
}
Отображение при ручном запуске сборки
Отображение при ручном запуске сборки
Результат вывода в консоль jenkins
Результат вывода в консоль jenkins

к содержанию


3. Credentials

Обратим внимание, что в выводе в консоль Jenkins нас предупреждает о том, что выводить значение пароля в echo используя Groovy String interpolation не является безопасным. 

Как же избежать возможной утечки пароля в данном случае?!

Самый простой вариант - это заменить двойные кавычки на одинарные.
О данной особенности не стоит забывать и при работе с методом credentials().

Результат выполнения

Метод credentials() поддерживает несколько вариантов:

  • secret text

  • usernames and passwords

  • secret files

  • Jenkins' Snippet Generator для других типов

Создание credential в Jenkins
  1. Перейдем в раздел credentials

  2. Выберем папку

  3. Выбираем домен

  4. Здесь отображаются уже существующие credentials. Их можно отредактировать. Нас интересует команда меню: Add credentials

  5. В нашем случае выберем тип Username and Password. Также существует плагин для Jenkins для интеграции с Vault.  Подробней https://plugins.jenkins.io/hashicorp-vault-plugin/

    Чек-бокс Treat username as secret не отображает username на списке credentials
    ID если не будет заполнено, сформируется автоматически

Для того чтобы credentials можно было использовать, необходимо объявить переменную:

environment {

        TEST_CREDS = credentials('4444444444444')

    }

здесь TEST_CREDS - это название переменной, а в скобках указан ID credentials

Также стоит отметить, что при обращении по имени переменной данные получаются в формате user:password. При необходимости получения непосредственно user или password к названию переменной добавляется _USR или _PSW соответственно. Объявлять эти переменные дополнительно не требуется.

Обращение к значению переменной осуществляется за счет указания знака$ перед названием переменной.

Пример

Добавим в наш пайплайн credentials и выведем их значение:

pipeline {
    agent {
        node {
            label 'jenkins-vm.company.ru'
        }
    }
 
    parameters {
        string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?')
 
        text(name: 'BIOGRAPHY', defaultValue: '', description: 'Enter some information about the person')
 
        booleanParam(name: 'TOGGLE', defaultValue: true, description: 'Toggle this value')
 
        choice(name: 'CHOICE', choices: ['One', 'Two', 'Three'], description: 'Pick something')
 
        password(name: 'PASSWORD', defaultValue: 'SECRET', description: 'Enter a password')
    }
    environment {
        TEST_CREDS = credentials('4444444444')
    }
    stages {
        stage('Example') {
            steps {
                echo "Hello ${params.PERSON}"
 
                echo "Biography: ${params.BIOGRAPHY}"
 
                echo "Toggle: ${params.TOGGLE}"
 
                echo "Choice: ${params.CHOICE}"
 
                echo 'Password: ${params.PASSWORD}'
                 
                echo 'from credentials: $TEST_CREDS'
                 
                echo "user from credentials: $TEST_CREDS_USR"
                 
                echo "password from credentials: $TEST_CREDS_PSW"
            }
        }
    }
}

Результат выполнения:

В данном случае даже использование двойных кавычек не выводит конкретное значение в консоль. Но все равно интерполяция является небезопасной, о чем нас предупреждает Jenkins. И рекомендуется использовать одинарные кавычки.

к содержанию


4. Триггеры сборки

Существует несколько вариантов триггеров сборки:
- Удаленный запуск сборки 
- Старт сборки после окончания сборки другого проекта
- Запуск периодически
- По изменениям в GitLab
- Триггер из артифактори
- Триггеры GitHub
- Scm изменения 

Самый популярный для запуска автотестов - это периодический запуск, например: ежедневно в 7 утра. Чтобы по началу рабочего дня было актуальное состояние прогона тестов.

Пример, ежедневный запуск в рабочие дни в 7.00: H 7 * * 1-5 

Синхронизация с GitLab

Полностью строка звучит "Build when a change is pushed to GitLab. GitLab webhook URL: https://company.jenkins.ru/project/TEST/ExampleMVN" 
Из названия нам потребуется URL. Именно на этот адрес GitLab будет отправлять события.

По каким же событиям Jenkins стартует сборку?

  1. любой Push в репозиторий

  2. Push в случае удалении ветки

  3. Создание любого Merge Request

  4. Создание Merge Request содержащего новые  коммиты

  5. Принятие  Merge Request

  6. Закрытие Merge Request

  7. Подтверждение Merge Request

  8. Если Merge Request содержит конкретный коммент

А теперь посмотрим,  что нужно сделать со стороны Gitlab.

В меню "Настройки" следует выбрать пункт "Webhooks"
В меню "Настройки" следует выбрать пункт "Webhooks"

Нам понадобится URL и Secret Token.
URL - указан в Jenkins когда мы проставляли чек-бокс по триггеру сборки. В нашем случае это https://company.jenkins.ru/project/TEST/ExampleMVN

Secret Token  - также берем из Jenkins из настроек триггера сборки по изменениям в Gitlab. Точнее, то значение которое мы укажем в Gitlab должно совпадать с указанным в Jenkins.

Генерация Secret Token 

  1. Необходимо перейти в Расширенные настройки триггер:

  2.  Нажать Generate 

  3. Скопировать сгенерированный код и вставить его в GitLab

После добавления webhook он отобразится внизу страницы

Можно проверить что все настроено корректно, нажав на кнопку Test. В случае если все сделано корректно, то появится уведомление 

к содержанию


5. Этапы/stages 

Основное описание того что проиcходит в Pipeline заключается как раз в блоке Stages. Блок Stages должен содержать минимум один этап (stage).  Рекомендуется делать этапы дискретными, например: Build, Test, and Deploy.

Каждый этап (stage) содержит:

  1. название, которое отображается в консоле при выполнении. Указывается в круглых скобках в одинарных кавычках

  2. непосредственно шаги выполнения (steps)

stages {
    stage('Example') {
        steps {
            echo 'Hello World'
        }
    }
}

5. 1 Клонирование репозитория

Одним из основных этапов сборки что для разработчиков, что для тестирования является интеграция с репозиторием для получения актуального состояния исходного кода. https://www.jenkins.io/doc/pipeline/steps/git/

В данном случае нам помогает плагин Jenkins https://plugins.jenkins.io/git/

Существует два варианта клонирования репозитория:

  • git step

  • checkout step

git step является более простым вариантом и соответственно менее функциональным.
checkout step лучше использовать с SCM checkout method. 

Рассмотрим простейший вариант git step. Подробнее про SCM checkout method можно прочитать https://plugins.jenkins.io/git/#plugin-content-pipeline-examples

Пример Pipeline, в котором клонируюется репозиторий
pipeline {
    agent {
        node {
            label 'jenkins-vm.company.ru'
        }
    }
    stages {
        stage('clone repo') {
            steps {
                git url: 'https://git.company.ru/java_example.git',
                credentialsId: '22222222',
                branch: 'master'
            }
        }
    }
}
Результат выполнения Pipeline
Результат выполнения Pipeline

Пример c checkout:

Stage('clone repo') {
    steps{
        checkout([$class : 'GitSCM', branches: [[name: '*/master']],
        doGenerateSubmoduleConfigurations: false,
        extensions                       : [],
        submoduleCfg                     : [],
        userRemoteConfigs                : [[credentialsId: '2222222222',
        url          :  'https://git.company.ru/java_example.git']]]
                )
            }
        }

5.2 Запуск тестов

После того как мы клонировали репозиторий с нашими автотестами, необходимо их запустить.

Запускаются они стандартной командой mvn (в данном случае) mvn clean install. Также можно указать версию jdk, maven. Команда запуска полностью дублируется той что мы запускаем у себя локально из консоли. Например: можно добавить запуск конкретного тестового набора (Test Suite).

stage('run tests') {
     steps{
          withMaven(jdk: 'JDK 8u172', maven: 'Maven 3.6.3') {
                             sh 'mvn clean install'
           }
     }
 }
Запуск конкретного сьюта автотестов
  1. Для этого в тестах у нас имеется аннотация Tag.

Значения SMOKE и REGRESS вынесены в отдельный класс как константы. И уже на их значение настраивается Pipeline

public class SuiteName {
    public static final String SMOKE = "smoke";
    public static final String REGRESS= "regress";
}
  1. В пайплайн добавим параметр:

parameters{choice(choices: ['regress', 'smoke',],
                  description: 'Выбор сьюта для запуска',
                  name: 'suiteToRun')}
  1. Отредактируем команду запуска:

sh 'mvn clean install -Dgroups=${suiteToRun}'

В итоге при запуске сборки запустятся только те автотесты, которые помечены соответствующей аннотацией.

к содержанию

5.3 Формирование отчета

После прогона тестов нам бы хотелось получить некий отчет о результатах выполнения автотестов.

Jenkins по умолчанию формирует отчет об упавших тестах, из которого видно:
- Кем был осуществлен запуск
- Сколько по времени выполнялось
- В каком репозитории лежат исходники
- Результаты теста в виде количества упавших тестов и с какой ошибкой, если провалиться в конкретный тест

Данный вариант не особо удобен в использовании и мало информативен для сотрудников, не связанных с написанием автотестов. Более читабельный формат с описанием непосредственно шагов автотеста позволяет сформировать allure report.  Jenkins умеет также с ним работать  https://www.jenkins.io/doc/pipeline/steps/allure-jenkins-plugin/

Чтобы Allure отчет был информативен нужно уделять внимание исходному коду и аннотациям Allure.  

Подробнее про Allure: официальная документация: https://docs.qameta.io/allure/#_junit_5

Для того, чтобы jenkins формировал allure-отчет, необходимо добавить в pipline соответствующий этап:


stage('run allure reports') {
            steps {
                allure([includeProperties: true,
                                      jdk: '',
                               properties: [],
                        reportBuildPolicy: 'ALWAYS',
                                  results: [[path: '**/allure-results']]
                ])
            }
        }

В результате у нас появился дополнительный этап и значок allure у сборки, нажав на который мы перейдем непосредственно в allure отчет

к содержанию


6. Нотификация

Post блок состоит из одного или нескольких шагов выполняющихся либо после конкретного stage либо после всех stage, в зависимости от его расположения в pipeline.

Блок post может содержать следующие условия выполнения:

  • always

  • changed

  • fixed

  • regression

  • aborted

  • failure

  • success

  • unstable

  • unsuccessfulcleanup

Подробнее https://www.jenkins.io/doc/book/pipeline/syntax/#post

Мы прогнали автотесты, сформировали отчет, но пока никто не знает об этом. 
Наша следующая задача - рассказать об этом всем заинтересованным лицам.
Варианты тут могут быть разные:

  • нотификация о начале тестирования (не в блоке Post)

  • нотификация только в случае упавших тестов

  • нотификация всегда по завершении

  • прочие варианты, которые можно придумать)

Но все они базируются на процессе нотификации.  Рассмотрим вариант нотификации по почте.

Отправка письма на почту

Для отправки письма на почту есть команда emailext(). Подробнее https://plugins.jenkins.io/email-ext/

Добавим в наш pipeline отправку сообщения, указав:

  • тему сообщения

  • тело (в теле добавим сразу ссылку на allure отчет)

  • адресатов

post {
    always{
        echo 'Pipeline is complete'
        emailext (
            subject: "CMXQA.TESTS Отчет прогона тестов [${env.BUILD_NUMBER}] ",
            body:"""Подробный allure-отчет: "<a href='${env.BUILD_URL}allure/'>${env.JOB_NAME} [${env.BUILD_NUMBER}]</a>"</p>""",
            to: "dminakova@cinimex.ru"
        )
    }
}

Pipeline from SCM

Ну и в завершении, хотелось бы отметить: bestPractice является хранение файла jenkins.pipeline вместе с кодом

В проекте создаем файл в корневом каталоге и называем его piplene.jenkinsfile. И это же название указываем в Script Path.

В самом файле указываем все то что у нас было в jenkins

Теги:
Хабы:
Всего голосов 4: ↑4 и ↓0+4
Комментарии7

Публикации

Информация

Сайт
www.cinimex.ru
Дата регистрации
Дата основания
1997
Численность
501–1 000 человек
Местоположение
Россия