Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Jenkins, Docker, два Pipeline

Jenkins, Docker, два Pipeline

Автоматизация тестирования распределенных систем с помощью Jenkins Pipeline библиотеки на основе Docker-контейнеризации

nikolai.smirnov

November 05, 2019
Tweet

More Decks by nikolai.smirnov

Other Decks in Programming

Transcript

  1. Jenkins, Docker, два Pipeline АВТОМАТИЗАЦИЯ ТЕСТИРОВАНИЯ РАСПРЕДЕЛЕННЫХ СИСТЕМ С ПОМОЩЬЮ

    JENKINS PIPELINE БИБЛИОТЕКИ НА ОСНОВЕ DOCKER-КОНТЕЙНЕРИЗАЦИИ Николай Смирнов | bercut.com
  2. Сколько времени требуется, чтобы прогнать 100 Jenkins задач с неизолированными

    интеграционными тестами, если каждая идет ~ 6 минут? 2
  3. Что такое платформа 4 Бизнес уровень Интеграционный уровень Уровень доступа

    Транспорт Service A Service B Scheduling Audit Управление\Мониторинг (agents) Service C SOA/R EST Service X Service X ORA PG Times Ten
  4. Термины и определения  Платформа – распределенная система для создания

    телеком- сервисов  Компоненты – сервисы в терминах SOA/микросервисной архитектуры  Системы – контейнеры компонентов (серверы BPEL, EventProcessing, AppServer)  Шина данных – клиент-серверная библиотека доставки сообщений (маршрутизация, резервирование, масштабирование) 5
  5. А давайте последовательно 1. Раскатываем окружение для теста/группы тестов 2.

    Запускаем тесты на системы + сервисы 3. Чистим за собой. Идем в п. 1. 9
  6. Типичные трудности тестирования  Отличия окружения стендов тестирования/разработки  Хрупкость

    настройки стендов  Cложность изоляции по данным в одной БД  Рутинное разворачивание новых сборок  Необходимость корректного cleanup после тестирования  «Эффект домино» при фейлах массового прогона 11
  7. Суть подхода  BUILD Тестируемые сущности (системы и компоненты) сохраняются

    в форме рабочих сервисов в Docker-образы  COMPOSE Jenkins pipeline задача «набирает» необходимые сервисы для формирования окружения под тесты  WRAP Системы под тестированием (docker-контейнеры) оборачиваются в лаконичный API в Global Pipeline Library – работа в тестах с ними в стиле ООП  RUSH Тесты запускаются параллельно благодаря изоляции окружения от др. задач и объединения сервисов в изолированную сеть Docker 12
  8. Dockerfile – как собрать образ Тэги образа: x.y x.y.z.k x.y---branchName

    (для систем, собранных на девелоперских ветках) BUILD 14
  9. Dockerfile – как собрать образ Тэги образа: x.y x.y.z.k x.y---branchName

    (для систем, собранных на девелоперских ветках) BUILD 14
  10. Dockerfile – как собрать образ Тэги образа: x.y x.y.z.k x.y---branchName

    (для систем, собранных на девелоперских ветках) BUILD 14
  11. docker-compose.yml version: "3" services: mysles: image: "dockerregistry:5000/tsles:${SLES_VERSION}" networks: sles_network: environment:

    - INST_NAME=${MYSLES_INST_NAME} ports: - "${MYSLES_HTTP_PORT}:8080" expose: - "8080" mainServer: image: "dockerregistry:5000/tlwsa:${LWSA_VERSION}" networks: sles_network: aliases: - mainServer networks: sles_network: export MYSLES_INST_NAME=mysles; \ export SLES_VERSION=3.4; \ export MYSLES_HTTP_PORT=18080; \ export LWSA_VERSION=latest; \ docker-compose up 16 COMPOSE
  12. Приятные следствия использования Docker  ConfigurationAsACode сервиса в Dockerfile: основа

    определяется в родительском образе «добрым дядей»  Развернуть систему – так же просто как вычекнуть из гита  Образы с готовыми схемами БД – plug’n’play с сервисом!  Использовать образы на локальной машине полезно: разработчикам и аналитикам для отладки и проверки гипотез  Контроль версий сервисов (по тегу) – тестирование совместимости и воспроизведение ошибок с прода, локализации версии с внесенным багом  Изоляция сети и параллелизм 17
  13. Какие тесты включить в Jenkins job?  Логическая группировка по

    проверяемому функционалу – Легко локализовать – Эффект «домино» сводится к минимуму – Пример: тесты на деплой сервиса, тесты на условную маршрутизацию по XPath, и т.п.  Один состав систем под тестированием для всех тестов в задаче – Легко исследовать окружение воспроизведения бага (параметр задачи keepAlive=true) 18
  14. Какие тесты автоматизируемы?  Функциональные интеграционные тесты – Инструменты: Pipeline

    Groovy, SoapUI, TestNG  Тесты на производительность. – load – stability – stress (max + disconnects) – functional + load – volume – CPU – RAM – TPS – AVG – etc. 20 Это вообще легально?
  15. 21

  16. Типовой Jenkinsfile #!groovy package tests.Bercut_JS @org.jenkinsci.plugins.workflow.libs.Library('bercut') import test.* node(Global.getNodeName(this)) {

    timestamps { try { Global.init(this) TestRail.runsByProject("RTSIB").attach() SLES sles = SLES.getInstance("sles") stage('Setup env') { Docker.composeUpServices(sles) Docker.waitStartup(sles) TestRail.useVersion = sles.getBuildNumber() } 23 SUT Wrapper
  17. Типовой Jenkinsfile. Продолжение stage('DeployBPELs') { sles.getDeployer().deployFromCMPortal( "PlTest/RTSIB_JS/TestBpelJavaScript").assertOk() } stage('Tests') {

    SoapUI.startTest("TestSuite", ["ip":"127.0.0.1:${sles.httpPort}"]) } stage('Report results') { Global.finishNormal() } } catch (Throwable e) { Global.finishException(e) } } } 24
  18. Logger. Ныряем глубже /** * log message with mark log

    level as info * @param message for logging * @param stack */ static void info(String message, StackTraceElement[] stack = null) { log(message, stack, Level.INFO.intLevel) } // Logger.groovy class 28
  19. Logger. Ныряем глубже. Продолжение /** * Logs to this build

    log file (log.txt). * @param message to log */ static void log(String message, StackTraceElement[] stack = null, Integer tlevel = Level.INFO.intLe if (tlevel < level.intLevel) { return } /* ... code here ... */ Level currentLevel = Level.fromIntValue(tlevel) Shell.execraw("printf \"[${TimeHelper.getFormattedJobDuration()}]" + " [%-${mWidth}s%${fWidth}s] [${currentLevel.displayName}]:" + " %s\\n\" \"${method}\" \"${file}\" \"${businessMessage}\" >> \"${logFilePath}\"") if (aScript != null) aScript.echo("[${currentLevel.displayName}] ${method}${file}: ${businessMessage}") } 29
  20. Logger. Ныряем глубже. Продолжение ещё  Shell.groovy класс static Result

    execraw(String command, Boolean silent = defaultSilent) { /* ... code here ... */ output = Global.script.sh( script: "${command}", returnStdout: true ) /* ... code here ... */ new Result(Integer.valueOf(status), output) } 30
  21. Создание окружения, SUT Wrappers  composeUpServices() – запускает сервисы в

    изолированной сети по YML – Сопоставление Groovy-объектов по именам сервисов в YML SLES client = SLES.getInstance("client", true) SLES serverSles = SLES.getInstance("server", true) LSC jumper = LSC.getInstance("jumper") LSC lwsa = LSC.getInstance("lwsa") Docker.composeUpServices(client, serverSles, jumper, lwsa) Docker.waitStartup(client, serverSles, jumper, lwsa) Добавить имя инстанса в MIB-дерево 33  composeUpServices() – запускает сервисы в изолированной сети по YML – Сопоставление Groovy-объектов по именам сервисов в YML
  22. Автоподстановка параметров  ${SLES_VERSION} заполняется в соответствии с параметром задачи

     ${<SERVICE_NAME>_*_PORT} – уникальные для задачи порты (авто) version: "3" services: client: image: "dockerregistry:5000/tsles:${SLES_VERSION}" networks: sles_network: aliases: - client ports: - "${CLIENT_HTTP_PORT:-8088}:8080" - "${CLIENT_AGENT_PORT:-2044}:2048" expose: - "8080" - "2048" Параметры заполняются фреймворком автоматически 34
  23. Разворачивание сервисов  Деплой, андеплой: – артефактов по расположению в

    структуре CMPortal – артефактов с диска – BPEL (jar), Service Adapter (war), Service Enabler (jar) client.getDeployer() .deployFromCMPortal("PlTest/Transport/TestRTSIBWeight_reply") serverSles.getDeployer() .deployFile("BPInvokesHello.jar") lwsa.getDeployer() .deployFromCMPortal("SDEP/AutoTest/SAHello") 35
  24. Управление приложением // создание конфигурационной переменной serverSles.getMessageBusMib() .createAndSetVariable( "Core/Configuration/Timeouts/DefaultExpectedQoSTimeout", Atlas.types.longint,

    "5") // чтение конфигурационной переменной String level = serverSles.getArtifactMib("BPHello", "1.0") .getVariable("Configuration/LogLevel") println(level) // выведет 'minimum' serverSles.stopFromMib(false) // сигнал остановки приложения assert serverSles.getMib() // ожидать значения стат. переменной .waitForValue("/Core/Statistics/Status", "turnedoff") 36
  25. Настройка ESB // создает физическое подключение к серверу SLES по

    ESB client.createRTSIBConnectionTo( serverSles, "tcpConnectionToServer") // создает логическое подключение до PortType к серверу client.addConnectionPT( "routeToServer", Atlas.escapeQName( "{http://bercut.org/wsdl/BPHello}HelloPortType"), "tcpConnectionToServer", "tcp") // очищает таблицу маршрутизации по PortType client.removeAllPortTypeRouting() 37
  26. Result  Модель результата выполнения команды/операции – Возвращает и Статус

    (OK, если код == 0) и консольный вывод  Композиция результатов – тоже результат Result r0 = Result.createOkResult() // конъюнкция результатов Result total = r0.append(r1).append(r2) println(total.isOk()) // успех, если все 3 результата успешны Result.allAreFailed(r0, r1) // успех, если все неуспешны Result.allArePassed(r0, r1) // успех, если все успешны Result.onlyOneIsPassed(r0, r1) // успех, если только 1 успешен Result.countPassed(r0, r1) // вернет количество успешных 38
  27. Работа с трейсами. TraceFetcher  Проверка (строгая и нестрогая) на

    содержимое логов  Логи нормализируются (UID заменяется на номер последовательности) TraceFetcher traceFetcher = TraceFetcher.getOne() // Запоминает время, когда начинаются полезные трейсы traceFetcher.setTraceStartingPoint() // Запуск тестов (система пишет трейсы) SoapUI.startTest("MulticastTestSuite", params, "nope MulticastGroup") // Валидация трейсов по содержимому Result total = Result.allArePassed( traceFetcher.fetchTrace(server.atlas) // проверка на содержание строки .containsString("Invoke operation 'MulticastOneWayOperation'"), traceFetcher.fetchTrace(client.atlas) // проверка на соотв-ие файлу .matchesFile("expect/TraceEthalon.txt")) println(total.isOk()) // успех, в случае если обе проверки прошли успешно 39
  28. TestRail и описания сценариев в коде ScenarioDescriptor.startCase(71798) ScenarioDescriptor.startStep( "Настройка HTTPS

    сервера", "Сервер принимает клиентские подключения") server.addSSLServer() ScenarioDescriptor.endStep() String connName = "https" client.createHTTPConnectionTo( connName, server.getHttpsAccessPoint(), 10, false, "persistance", "https", ["${PORT_TYPE}": PORT_TYPE_URI]) 40
  29. TestRail и отправка результатов  Парсинг отчетов SoapUI после прогона

    (автоматическая связь по ID из SoapUI кейса)  Явная отправка результатов по кейсу: TestRail.addResultIf(12345, abonFound, "Абонент не найден!") TestRail.addResultIfEq(12346, server.getMib().getVariable("Version"), "1.0", "Версия не совпала с 1.0") TestRail.addResultIfValueInRange(12347, actualValue, 3.14, 0.5) TestRail.addResult(12348, resultObject) 42
  30. Страница статистики  100 Jenkins задач  2500 тест кейсов

     10 автоматизированных тестов на производительность  Время параллельного прогона 2 часа  Время последовательного прогона 10 часов  Ресурсы – 4 машины: 8 CPU, 8GB RAM, 20..50GB HDD – Количество Jenkins executor: 3 43
  31. Параллельная разработка в GIT Параллельная разработка Beluha – Использование с

    @Library('bercut@experimental_branch') – Клон Jenkins Job с Jenkinsfile из другой experimental_branch – Безопасная разработка и отладка  Тестирование систем на бранчах – Образы с бранча собираются со спец тэгом x.y---<branch> – Все тесты параметризованы версиями сервисов (бранч входит в этот параметр) – Разработчики самостоятельно запускают тесты на бранчах 44
  32. Проблемы  Отсутствие дебаг (YAGNI?) – изоляция от Pipeline Syntax

    – отладка Groovy  Pipeline порождает много мелких файлов – заканчиваются inodes, нагрузка на IO, дисковое пространство мастера  Jenkins Groovy не совсем Groovy 45
  33. О компании Bercut 25+ лет на рынке телекоммуникаций Наша команда

    создаёт и внедряет бизнес-продукты, кастомизированные решения и тиражируемый софт для операторов связи по всему миру. Партнеры Клиенты — крупнейшие мировые операторы связи и сервис-провайдеры 1000+ инсталляций в разных странах 300+ млн абонентов пользуются услугами на базе решений Bercut Ключевые клиенты 46
  34. Ссылки 1) Traditional Development/Integration/Staging/Production Practice for Software Development – 2006

    – https://dltj.org/article/software-development-practice/ 2) Андрей Маркелов. Интеграционное тестирование зоопарка микросервисов с помощью TestContainers и JUnit 5 – 2018 – https://2018.heisenbug-moscow.ru/2018/msk/talks/4gjiduaauwiiayoaygmki6/ 3) William Morgan. Что такое service mesh и почему он мне нужен. Перевод. – 2017 – https://habr.com/ru/company/flant/blog/327536/ 47
  35. Обо мне  Смирнов Николай Георгиевич  Руководитель группы автоматизации

    тестирования отдела Платформы компании Беркут с 2018 г.  Программист Java с 2007, Groovy c 2018  [email protected]  https://t.me/nikolaismirnov 48