Yazılımınızı test etmenin önemli ve gerekli olduğunu herkesin çok iyi bilmesine ve birçoğunun bunu uzun süredir otomatik olarak yapmasına rağmen, Habr'ın geniş topraklarında bu kadar popüler ürünlerin bir kombinasyonunu oluşturmak için tek bir tarif yoktu. Bu niş (en sevdiğimiz) GitLab ve JUnit olarak. Bu boşluğu dolduralım!
Giriş
Öncelikle biraz bağlam aktarayım:
Tüm uygulamalarımız Kubernetes üzerinde çalıştığından testleri uygun altyapı üzerinde çalıştırmayı değerlendireceğiz.
Montaj ve dağıtım için kullanıyoruz Werf (altyapı bileşenleri açısından bu aynı zamanda otomatik olarak Helm'in de dahil olduğu anlamına gelir).
Gerçek test oluşturma ayrıntılarına girmeyeceğim: bizim durumumuzda müşteri testleri kendisi yazar ve biz yalnızca bunların başlatılmasını (ve birleştirme talebinde ilgili bir raporun varlığını) sağlarız.
Genel eylem sırası nasıl görünecek?
Uygulamanın oluşturulması - bu aşamanın açıklamasını atlayacağız.
Uygulamayı Kubernetes kümesinin ayrı bir ad alanına dağıtın ve test etmeye başlayın.
Yapıları arama ve JUnit raporlarını GitLab ile ayrıştırma.
Daha önce oluşturulmuş bir ad alanını silme.
Şimdi - uygulamaya!
Ayar
GitLab CI
Bir parçayla başlayalım .gitlab-ci.yaml, uygulamanın dağıtılmasını ve testlerin çalıştırılmasını açıklar. Listenin oldukça hacimli olduğu ortaya çıktı, bu nedenle yorumlarla tamamen desteklendi:
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
Şimdi dizinde .helm/templates hadi Job ile YAML oluşturalım - tests-job.yaml — testleri ve ihtiyaç duyduğu Kubernetes kaynaklarını çalıştırmak için. Listelemeden sonra açıklamalara bakın:
Ne tür kaynaklar Bu konfigürasyonda tanımlandı mı? Dağıtım sırasında proje için benzersiz bir ad alanı oluştururuz (bu, .gitlab-ci.yaml - tests-${CI_COMMIT_REF_SLUG}) ve yuvarlayın:
Yapılandırma haritası test komut dosyasıyla;
İş bölmenin açıklaması ve belirtilen direktifle birlikte commandsadece testleri çalıştıran;
PV ve PVCtest verilerini saklamanıza olanak tanır.
Giriş durumuna dikkat edin if bildirimin başında - buna göre, Helm grafiğinin uygulamayla birlikte diğer YAML dosyaları sarılmalıdır обратную test sırasında konuşlandırılmayacak şekilde tasarlayın. Yani:
{{- if ne .Values.global.run_tests "yes" }}
---
я другой ямлик
{{- end }}
Ancak eğer testler biraz altyapı gerektiriyor (örneğin, Redis, RabbitMQ, Mongo, PostgreSQL...) - YAML'leri hayır kapamak. Bunları bir test ortamına da dağıtın... Elbette uygun gördüğünüz şekilde ayarlayın.
Son dokunuş
Çünkü werf kullanarak montaj ve dağıtım şimdilik çalışıyor sadece derleme sunucusunda (gitlab-runner ile) ve testlerin bulunduğu bölme ana bilgisayarda başlatıldığında, bir dizin oluşturmanız gerekecektir. /mnt/tests ustaya ve koşucuya ver, örneğin, NFS yoluyla. Açıklamalarla birlikte ayrıntılı bir örneği şu adreste bulabilirsiniz: K8'in belgeleri.
Hiç kimse doğrudan gitlab-runner'da bir NFS paylaşımı yapmayı ve ardından bunu bölmelere monte etmeyi yasaklamaz.
Dikkat
Doğrudan kabuk çalıştırıcısında testlerle bir komut dosyası çalıştırabiliyorsanız, bir İş oluşturarak neden her şeyi karmaşık hale getirdiğinizi soruyor olabilirsiniz? Cevap oldukça önemsiz...
Bazı testlerin doğru çalıştığını doğrulamak için altyapıya (MongoDB, RabbitMQ, PostgreSQL vb.) erişim gerekir. Testleri birleştirilmiş hale getiriyoruz; bu yaklaşımla bu tür ek birimlerin dahil edilmesi kolaylaşıyor. Buna ek olarak şunu alıyoruz: standart dağıtım yaklaşımı (NFS kullanılıyor olsa bile, dizinlerin ek montajı).
sonuç
Hazırlanan konfigürasyonu uyguladığımızda ne göreceğiz?
Birleştirme isteği, en son ardışık düzende çalıştırılan testlere ilişkin özet istatistikleri gösterecektir:
Ayrıntılar için her hataya buraya tıklanabilir:
NB: Dikkatli okuyucu, bir NodeJS uygulamasını test ettiğimizi ve ekran görüntülerinde - .NET... Şaşırmayın: makaleyi hazırlarken ilk uygulamanın testinde hiçbir hata bulunamadı, ancak onlar başka birinde bulundu.
Sonuç
Gördüğünüz gibi karmaşık bir şey yok!
Prensip olarak, zaten bir kabuk toplayıcınız varsa ve çalışıyorsa ancak Kubernetes'e ihtiyacınız yoksa, buna test eklemek burada açıklanandan daha basit bir görev olacaktır. Ve GitLab CI belgeleri Ruby, Go, Gradle, Maven ve diğerleri için örnekler bulacaksınız.