Nepaisant to, kad visi puikiai žino, kad jūsų programinės įrangos testavimas yra svarbus ir būtinas, o daugelis jau ilgą laiką tai daro automatiškai, Habro platybėse nebuvo vieno recepto, kaip sukurti tokių populiarių produktų derinį. ši niša kaip (mūsų mėgstamiausia) „GitLab“ ir „JUnit“. Užpildykime šią spragą!
Įžanginis
Pirmiausia leiskite man pateikti šiek tiek konteksto:
Kadangi visos mūsų programos veikia Kubernetes, apsvarstysime galimybę atlikti atitinkamos infrastruktūros bandymus.
Surinkimui ir diegimui naudojame werf (Kalbant apie infrastruktūros komponentus, tai taip pat automatiškai reiškia, kad Helmas dalyvauja).
Į faktinio testų kūrimo detales nesileisiu: mūsų atveju klientas pats rašo testus, o mes tik užtikriname jų paleidimą (ir atitinkamos ataskaitos buvimą sujungimo užklausoje).
Kaip atrodys bendra veiksmų seka?
Programos kūrimas – šio etapo aprašymo praleisime.
Įdiekite programą į atskirą Kubernetes klasterio vardų sritį ir pradėkite testavimą.
Artefaktų paieška ir JUnit ataskaitų analizavimas naudojant „GitLab“.
Anksčiau sukurtos vardų erdvės ištrynimas.
Dabar – prie įgyvendinimo!
reguliavimas
„GitLab CI“
Pradėkime nuo fragmento .gitlab-ci.yaml, kuriame aprašomas programos diegimas ir bandymų vykdymas. Sąrašas pasirodė gana didelis, todėl buvo kruopščiai papildytas komentarais:
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
Dabar kataloge .helm/templates sukurkime YAML su Job - tests-job.yaml — atlikti testus ir jai reikalingus Kubernetes išteklius. Žr. paaiškinimus po įtraukimo į sąrašą:
Kokie ištekliai aprašyta šioje konfigūracijoje? Diegdami sukuriame unikalią projekto vardų erdvę (tai nurodyta .gitlab-ci.yaml - tests-${CI_COMMIT_REF_SLUG}) ir išskleiskite:
„ConfigMap“ su testo scenarijumi;
darbas su ankšties aprašymu ir nurodyta direktyva command, kuri tiesiog atlieka testus;
PV ir PVC, kurios leidžia saugoti bandymo duomenis.
Atkreipkite dėmesį į įvadinę sąlygą su if manifesto pradžioje - atitinkamai kiti Helm diagramos YAML failai su programa turi būti suvynioti į atvirkščiai suprojektuoti taip, kad bandymo metu jie nebūtų naudojami. Tai yra:
{{- if ne .Values.global.run_tests "yes" }}
---
я другой ямлик
{{- end }}
Tačiau jei bandymai reikia tam tikros infrastruktūros (pvz., Redis, RabbitMQ, Mongo, PostgreSQL...) – jų YAML gali būti ne Išjunk. Įdiekite juos ir į bandomąją aplinką... žinoma, pakoreguokite, kaip jums atrodo tinkama.
Galutinis prisilietimas
Nes surinkimas ir diegimas naudojant werf darbus tik kūrimo serveryje (su gitlab-runner), o pod su testais paleidžiamas pagrindiniame kompiuteryje, turėsite sukurti katalogą /mnt/tests ant šeimininko ir atiduok bėgikui, pavyzdžiui, per NFS. Išsamų pavyzdį su paaiškinimais galite rasti K8s dokumentacija.
Niekas nedraudžia kurti NFS bendrinimo tiesiogiai „gitlab-runner“, o vėliau jį prijungti prie lizdų.
Atkreipti dėmesį
Galbūt klausiate, kam viską komplikuoti kuriant darbą, jei galite tiesiog paleisti scenarijų su testais tiesiogiai apvalkalo vykdyklyje? Atsakymas gana trivialus...
Kai kuriems bandymams reikalinga prieiga prie infrastruktūros (MongoDB, RabbitMQ, PostgreSQL ir kt.), kad būtų patikrinta, ar jie veikia tinkamai. Testavimą suvienodiname – taikant šį metodą tampa lengva įtraukti tokius papildomus objektus. Be to, mes gauname standartas diegimo metodas (net jei naudojamas NFS, papildomas katalogų montavimas).
Rezultatas
Ką matysime, kai pritaikysime paruoštą konfigūraciją?
Sujungimo užklausoje bus rodoma naujausio bandymo atliktų bandymų statistikos suvestinė:
Kiekvieną klaidą galite spustelėti čia, kad gautumėte daugiau informacijos:
NB: Dėmesingas skaitytojas pastebės, kad mes testuojame NodeJS aplikaciją, o ekrano nuotraukose - .NET... Nenustebkite: tiesiog rengiant straipsnį, testuojant pirmąją aplikaciją klaidų nerasta, tačiau jos buvo rasti kitame.
išvada
Kaip matote, nieko sudėtingo!
Iš principo, jei jau turite apvalkalo kolekcionierių ir jis veikia, bet jums nereikia Kubernetes, prie jo pritvirtinti testavimą bus dar paprastesnė užduotis nei aprašyta čia. Ir į GitLab CI dokumentacija rasite Ruby, Go, Gradle, Maven ir kai kurių kitų pavyzdžių.