Huolimatta siitä, että kaikki tietävät täydellisesti, että ohjelmistojen testaus on tärkeää ja tarpeellista, ja monet ovat tehneet sitä automaattisesti jo pitkään, Habrin laajuudessa ei ollut yhtä reseptiä niin suosittujen tuotteiden yhdistelmän luomiseen. tämä markkinarako kuten (suosikkimme) GitLab ja JUnit . Täytetään tämä aukko!
johdannossa
Aluksi kerron hieman kontekstista:
Koska kaikki sovelluksemme toimivat Kubernetesissa, harkitsemme testien suorittamista sopivassa infrastruktuurissa.
Käytämme kokoonpanoon ja käyttöönottoon werf (infrastruktuurikomponenttien kannalta tämä tarkoittaa myös automaattisesti, että Helm on mukana).
En mene yksityiskohtiin varsinaiseen testien luomiseen: meidän tapauksessamme asiakas kirjoittaa testit itse, ja varmistamme vain niiden käynnistämisen (ja vastaavan raportin läsnäolon yhdistämispyynnössä).
Miltä toimintojen yleinen järjestys näyttää?
Sovelluksen rakentaminen - jätämme pois tämän vaiheen kuvauksen.
Ota sovellus käyttöön Kubernetes-klusterin erilliseen nimiavaruuteen ja aloita testaus.
Artefaktien etsiminen ja JUnit-raporttien jäsentäminen GitLabin avulla.
Aiemmin luodun nimitilan poistaminen.
Nyt - toteutukseen!
säätö
GitLab CI
Aloitetaan fragmentilla .gitlab-ci.yaml, joka kuvaa sovelluksen käyttöönottoa ja testien suorittamista. Listaus osoittautui melko laajaksi, joten sitä täydennettiin perusteellisesti kommenteilla:
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
Nyt hakemistossa .helm/templates luodaan YAML Jobin kanssa - tests-job.yaml — suorittaa testejä ja sen tarvitsemia Kubernetes-resursseja. Katso selitykset listauksen jälkeen:
Millaisia resursseja kuvattu tässä kokoonpanossa? Käyttöönoton yhteydessä luomme projektille ainutlaatuisen nimiavaruuden (tämä on ilmoitettu kohdassa .gitlab-ci.yaml - tests-${CI_COMMIT_REF_SLUG}) ja rullaa se ulos:
ConfigMap testikirjoituksen kanssa;
Job podin kuvauksen ja määritetyn direktiivin kanssa command, joka vain suorittaa testit;
PV ja PVC, joiden avulla voit tallentaa testitietoja.
Kiinnitä huomiota johdantoehtoon if manifestin alussa - vastaavasti muut ruorikaavion YAML-tiedostot sovelluksen kanssa on käärittävä päinvastoin suunnitella niin, että ne eivät pääse leviämään testauksen aikana. Tuo on:
{{- if ne .Values.global.run_tests "yes" }}
---
я другой ямлик
{{- end }}
Kuitenkin, jos testit vaativat jonkin verran infrastruktuuria (esimerkiksi Redis, RabbitMQ, Mongo, PostgreSQL...) - niiden YAML:t voivat olla ei sammuttaa. Ota ne käyttöön myös testiympäristössä... säätämällä niitä tietysti parhaaksi katsomallasi tavalla.
Lopullinen kosketus
Koska kokoonpano ja käyttöönotto werf-teoksilla toistaiseksi vain rakennuspalvelimella (gitlab-runnerilla) ja testejä sisältävä pod käynnistetään isäntäkoneessa, sinun on luotava hakemisto /mnt/tests isännille ja anna se juoksijalle, esimerkiksi NFS:n kautta. Yksityiskohtainen esimerkki selityksineen löytyy osoitteesta K8:n dokumentaatio.
Kukaan ei kiellä tekemästä NFS-jakoa suoraan gitlab-runneriin ja sitten asentamasta sitä podeihin.
Huomata
Saatat kysyä, miksi monimutkaistaa kaikkea luomalla työ, jos voit yksinkertaisesti ajaa komentosarjan testeillä suoraan shell runnerissa? Vastaus on aika triviaali...
Jotkut testit vaativat pääsyn infrastruktuuriin (MongoDB, RabbitMQ, PostgreSQL jne.) varmistaakseen, että ne toimivat oikein. Teemme testauksesta yhtenäisen – tällä lähestymistavalla on helppoa sisällyttää tällaisia lisäkokonaisuuksia. Tämän lisäksi saamme standardi käyttöönottotapa (vaikka käytettäisiin NFS:ää, hakemistojen lisäasennus).
Tulos
Mitä näemme, kun käytämme valmisteltua kokoonpanoa?
Yhdistämispyyntö näyttää yhteenvetotilastot viimeisimmässä putkistossaan suoritetuista testeistä:
Jokainen virhe voidaan napsauttaa tästä saadaksesi lisätietoja:
NB: Huomaavainen lukija huomaa, että testaamme NodeJS-sovellusta, ja kuvakaappauksissa - .NET... Älä ihmettele: artikkelia valmisteltaessa ei vain löytynyt virheitä ensimmäisen sovelluksen testauksessa, mutta ne löytyivät toisesta.
Johtopäätös
Kuten näette, ei mitään monimutkaista!
Periaatteessa, jos sinulla on jo shell-keräilijä ja se toimii, mutta et tarvitse Kubernetesia, testauksen liittäminen siihen on vielä yksinkertaisempi tehtävä kuin tässä kuvattu. Ja sisään GitLab CI -dokumentaatio löydät esimerkkejä Rubysta, Gosta, Gradlesta, Mavenista ja joistakin muista.