Neskatoties uz to, ka visi lieliski zina, ka programmatūras testēšana ir svarīga un nepieciešama, un daudzi to jau ilgu laiku ir darījuši automātiski, Habras plašumos nebija nevienas receptes, kā izveidot tik populāru produktu kombināciju. šo nišu kā (mūsu iecienītāko) GitLab un JUnit. Aizpildīsim šo robu!
Ievads
Vispirms ļaujiet man sniegt kontekstu:
Tā kā visas mūsu lietojumprogrammas darbojas Kubernetes, mēs apsvērsim iespēju veikt testus atbilstošajā infrastruktūrā.
Montāžai un izvietošanai mēs izmantojam werf (infrastruktūras komponentu ziņā tas automātiski nozīmē arī Helma iesaistīšanos).
Es neiedziļināšos detaļās par reālo testu izveidi: mūsu gadījumā klients pats raksta testus, un mēs nodrošinām tikai to palaišanu (un atbilstoša ziņojuma esamību apvienošanas pieprasījumā).
Kāda izskatīsies vispārējā darbību secība?
Lietojumprogrammas izveide – šī posma aprakstu izlaidīsim.
Izvietojiet lietojumprogrammu atsevišķā Kubernetes klastera nosaukumvietā un sāciet testēšanu.
Artefaktu meklēšana un JUnit pārskatu parsēšana, izmantojot GitLab.
Iepriekš izveidotās nosaukumvietas dzēšana.
Tagad - pie ieviešanas!
koriģēšana
GitLab CI
Sāksim ar fragmentu .gitlab-ci.yaml, kurā aprakstīta lietojumprogrammas izvietošana un testu izpilde. Saraksts izrādījās diezgan apjomīgs, tāpēc tas tika rūpīgi papildināts ar komentāriem:
variables:
# объявляем версию werf, которую собираемся использовать
WERF_VERSION: "1.0 beta"
.base_deploy: &base_deploy
script:
# создаем namespace в K8s, если его нет
- kubectl --context="${WERF_KUBE_CONTEXT}" get ns ${CI_ENVIRONMENT_SLUG} || kubectl create ns ${CI_ENVIRONMENT_SLUG}
# загружаем werf и деплоим — подробнее об этом см. в документации
# (https://werf.io/how_to/gitlab_ci_cd_integration.html#deploy-stage)
- type multiwerf && source <(multiwerf use ${WERF_VERSION})
- werf version
- type werf && source <(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose)
- werf deploy --stages-storage :local
--namespace ${CI_ENVIRONMENT_SLUG}
--set "global.commit_ref_slug=${CI_COMMIT_REF_SLUG:-''}"
# передаем переменную `run_tests`
# она будет использоваться в рендере Helm-релиза
--set "global.run_tests=${RUN_TESTS:-no}"
--set "global.env=${CI_ENVIRONMENT_SLUG}"
# изменяем timeout (бывают долгие тесты) и передаем его в релиз
--set "global.ci_timeout=${CI_TIMEOUT:-900}"
--timeout ${CI_TIMEOUT:-900}
dependencies:
- Build
.test-base: &test-base
extends: .base_deploy
before_script:
# создаем директорию для будущего отчета, исходя из $CI_COMMIT_REF_SLUG
- mkdir /mnt/tests/${CI_COMMIT_REF_SLUG} || true
# вынужденный костыль, т.к. GitLab хочет получить артефакты в своем build-dir’е
- mkdir ./tests || true
- ln -s /mnt/tests/${CI_COMMIT_REF_SLUG} ./tests/${CI_COMMIT_REF_SLUG}
after_script:
# после окончания тестов удаляем релиз вместе с Job’ом
# (и, возможно, его инфраструктурой)
- type multiwerf && source <(multiwerf use ${WERF_VERSION})
- werf version
- type werf && source <(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose)
- werf dismiss --namespace ${CI_ENVIRONMENT_SLUG} --with-namespace
# мы разрешаем падения, но вы можете сделать иначе
allow_failure: true
variables:
RUN_TESTS: 'yes'
# задаем контекст в werf
# (https://werf.io/how_to/gitlab_ci_cd_integration.html#infrastructure)
WERF_KUBE_CONTEXT: 'admin@stage-cluster'
tags:
# используем раннер с тегом `werf-runner`
- werf-runner
artifacts:
# требуется собрать артефакт для того, чтобы его можно было увидеть
# в пайплайне и скачать — например, для более вдумчивого изучения
paths:
- ./tests/${CI_COMMIT_REF_SLUG}/*
# артефакты старше недели будут удалены
expire_in: 7 day
# важно: эти строки отвечают за парсинг отчета GitLab’ом
reports:
junit: ./tests/${CI_COMMIT_REF_SLUG}/report.xml
# для упрощения здесь показаны всего две стадии
# в реальности же у вас их будет больше — как минимум из-за деплоя
stages:
- build
- tests
build:
stage: build
script:
# сборка — снова по документации по werf
# (https://werf.io/how_to/gitlab_ci_cd_integration.html#build-stage)
- type multiwerf && source <(multiwerf use ${WERF_VERSION})
- werf version
- type werf && source <(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose)
- werf build-and-publish --stages-storage :local
tags:
- werf-runner
except:
- schedules
run tests:
<<: *test-base
environment:
# "сама соль" именования namespace’а
# (https://docs.gitlab.com/ce/ci/variables/predefined_variables.html)
name: tests-${CI_COMMIT_REF_SLUG}
stage: tests
except:
- schedules
Kubernetes
Tagad direktorijā .helm/templates izveidosim YAML ar Jobu - tests-job.yaml — veikt testus un tai nepieciešamos Kubernetes resursus. Skatiet paskaidrojumus pēc iekļaušanas sarakstā:
Kādi resursi aprakstīts šajā konfigurācijā? Izvietojot, mēs izveidojam unikālu projekta nosaukumvietu (tas ir norādīts .gitlab-ci.yaml Sākot no tests-${CI_COMMIT_REF_SLUG}) un izrullējiet to:
ConfigMap ar testa skriptu;
Darbs ar pod aprakstu un norādīto direktīvu command, kas tikai palaiž testus;
PV un PVC, kas ļauj saglabāt testa datus.
Pievērsiet uzmanību ievada nosacījumam ar if manifesta sākumā - attiecīgi citi Helm diagrammas YAML faili ar lietojumprogrammu ir jāiesaiņo otrādi dizains tā, lai tie netiktu izvietoti testēšanas laikā. Tas ir:
{{- if ne .Values.global.run_tests "yes" }}
---
я другой ямлик
{{- end }}
Tomēr, ja pārbaudes nepieciešama noteikta infrastruktūra (piemēram, Redis, RabbitMQ, Mongo, PostgreSQL...) - to YAML var būt nē izslēgt. Izvietojiet tos arī testa vidē... protams, pielāgojiet tos pēc saviem ieskatiem.
Galīgais pieskāriens
Jo montāža un izvietošana, izmantojot werf, joprojām darbojas tikai būvēšanas serverī (ar gitlab-runner), un pods ar testiem tiek palaists galvenajā datorā, jums būs jāizveido direktorijs /mnt/tests uz meistara un iedod to skrējējam, piemēram, izmantojot NFS. Detalizētu piemēru ar paskaidrojumiem var atrast K8s dokumentācija.
Neviens neaizliedz izveidot NFS koplietojumu tieši gitlab-runner un pēc tam uzstādīt to podiņos.
Piezīme
Iespējams, jūs jautāsiet, kāpēc visu sarežģīt, izveidojot darbu, ja varat vienkārši palaist skriptu ar testiem tieši čaulas palaidējā? Atbilde ir diezgan triviāla...
Dažiem testiem ir nepieciešama piekļuve infrastruktūrai (MongoDB, RabbitMQ, PostgreSQL utt.), lai pārbaudītu, vai tie darbojas pareizi. Mēs padarām testēšanu vienotu — ar šo pieeju ir viegli iekļaut šādas papildu entītijas. Papildus tam mēs iegūstam standarts izvietošanas pieeja (pat ja tiek izmantota NFS, papildu direktoriju montāža).
Piedzīvojiet efektīvu rezultātu spēku
Ko mēs redzēsim, kad izmantosim sagatavoto konfigurāciju?
Apvienošanas pieprasījumā tiks rādīta jaunākajā konveijerā veikto testu statistikas kopsavilkums:
Par katru kļūdu var noklikšķināt šeit, lai iegūtu sīkāku informāciju:
NB: Vērīgs lasītājs pamanīs, ka mēs testējam NodeJS aplikāciju, un ekrānšāviņos - .NET... Nebrīnieties: vienkārši gatavojot rakstu, pirmās aplikācijas testēšanā kļūdas netika atrastas, taču tās tika atrasti citā.
Secinājums
Kā redzat, nekas sarežģīts!
Principā, ja jums jau ir čaulas savācējs un tas darbojas, bet jums nav nepieciešams Kubernetes, testēšanas pievienošana tam būs vēl vienkāršāka, nekā šeit aprakstīts. Un iekšā GitLab CI dokumentācija jūs atradīsiet piemērus Ruby, Go, Gradle, Maven un dažiem citiem.