Përkundër faktit se të gjithë e dinë shumë mirë se testimi i softuerit tuaj është i rëndësishëm dhe i nevojshëm, dhe shumë prej tyre e kanë bërë automatikisht për një kohë të gjatë, në pafundësinë e Habrit nuk kishte asnjë recetë të vetme për vendosjen e një kombinimi të produkteve kaq të njohura në këtë vend si (i preferuari ynë) GitLab dhe JUnit. Le ta mbushim këtë boshllëk!
hyrëse
Së pari, më lejoni të jap një kontekst:
Meqenëse të gjitha aplikacionet tona funksionojnë në Kubernetes, ne do të shqyrtojmë ekzekutimin e testeve në infrastrukturën e duhur.
Për montim dhe vendosje ne përdorim werf (përsa i përket komponentëve të infrastrukturës, kjo gjithashtu automatikisht do të thotë që Helm është i përfshirë).
Unë nuk do të hyj në detajet e krijimit aktual të testeve: në rastin tonë, klienti i shkruan vetë testet, dhe ne vetëm sigurojmë nisjen e tyre (dhe praninë e një raporti përkatës në kërkesën për bashkim).
Si do të duket sekuenca e përgjithshme e veprimeve?
Ndërtimi i aplikacionit - ne do të heqim përshkrimin e kësaj faze.
Vendoseni aplikacionin në një hapësirë emri të veçantë të grupit Kubernetes dhe filloni testimin.
Kërkimi i objekteve dhe analizimi i raporteve të JUnit me GitLab.
Fshirja e një hapësire emri të krijuar më parë.
Tani - në zbatim!
rregullim
GitLab CI
Le të fillojmë me një fragment .gitlab-ci.yaml, i cili përshkruan vendosjen e aplikacionit dhe ekzekutimin e testeve. Lista doli të ishte mjaft voluminoze, kështu që u plotësua plotësisht me komente:
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
Tani në drejtori .helm/templates le të krijojmë YAML me Job - tests-job.yaml — për të ekzekutuar testet dhe burimet e Kubernetes që i nevojiten. Shihni shpjegimet pas renditjes:
Çfarë lloj burimesh përshkruar në këtë konfigurim? Gjatë vendosjes, ne krijojmë një hapësirë unike emri për projektin (kjo tregohet në .gitlab-ci.yaml - tests-${CI_COMMIT_REF_SLUG}) dhe shpërndajeni:
ConfigMap me skenar testimi;
punë me një përshkrim të pod dhe direktivën e specifikuar command, i cili thjesht kryen testet;
PV dhe PVC, të cilat ju lejojnë të ruani të dhënat e provës.
Kushtojini vëmendje gjendjes hyrëse me if në fillim të manifestit - në përputhje me rrethanat, skedarët e tjerë YAML të tabelës Helm me aplikacionin duhet të mbështillen në anasjelltas dizajnoni në mënyrë që ato të mos vendosen gjatë testimit. Kjo eshte:
{{- if ne .Values.global.run_tests "yes" }}
---
я другой ямлик
{{- end }}
Megjithatë, nëse testet kërkojnë pak infrastrukturë (për shembull, Redis, RabbitMQ, Mongo, PostgreSQL...) - YAML-të e tyre mund të jenë jo fiket. Vendosini ato edhe në një mjedis testimi... duke i rregulluar siç e shihni të arsyeshme, natyrisht.
Prekja e fundit
Sepse montimi dhe vendosja duke përdorur punimet werf tani për tani vetëm në serverin e ndërtimit (me gitlab-runner), dhe pod me teste lëshohet në master, do t'ju duhet të krijoni një drejtori /mnt/tests mbi mjeshtrin dhe ia jepni vrapuesit, për shembull, nëpërmjet NFS. Një shembull i detajuar me shpjegime mund të gjendet në Dokumentacioni K8s.
Askush nuk e ndalon krijimin e një share NFS direkt në gitlab-runner, dhe më pas montimin e tij në pods.
Shënim
Ju mund të pyesni pse të komplikoni gjithçka duke krijuar një punë nëse thjesht mund të ekzekutoni një skript me teste direkt në shell runner? Përgjigja është mjaft e parëndësishme...
Disa teste kërkojnë qasje në infrastrukturë (MongoDB, RabbitMQ, PostgreSQL, etj.) për të verifikuar që ato funksionojnë siç duhet. Ne e bëjmë testimin të unifikuar - me këtë qasje, bëhet e lehtë të përfshihen entitete të tilla shtesë. Përveç kësaj, ne marrim standard qasja e vendosjes (edhe nëse përdorni NFS, montim shtesë të drejtorive).
Result
Çfarë do të shohim kur të aplikojmë konfigurimin e përgatitur?
Kërkesa për bashkim do të tregojë statistika përmbledhëse për testet e kryera në tubacionin e saj të fundit:
Çdo gabim mund të klikohet këtu për detaje:
NB: Lexuesi i vëmendshëm do të vërejë se ne po testojmë një aplikacion NodeJS, dhe në pamjet e ekranit - .NET... Mos u çuditni: thjesht gjatë përgatitjes së artikullit nuk u gjetën gabime në testimin e aplikacionit të parë, por ato janë gjetur në një tjetër.
Përfundim
Siç mund ta shihni, asgjë e komplikuar!
Në parim, nëse tashmë keni një koleksionist guaskë dhe funksionon, por nuk keni nevojë për Kubernetes, bashkëngjitja e testimit me të do të jetë një detyrë edhe më e thjeshtë sesa përshkruhet këtu. Dhe ne Dokumentacioni GitLab CI do të gjeni shembuj për Ruby, Go, Gradle, Maven dhe disa të tjerë.