A pesar de que todos saben que es importante y necesario probar su software, y muchos lo han estado haciendo automáticamente durante mucho tiempo, no hay una sola receta para configurar un montón de productos tan populares en este nicho como (querido) GitLab y JUnit . ¡Llena este vacío!

Introductorio
Primero, describiré el contexto:
- Dado que todas nuestras aplicaciones funcionan en Kubernetes, consideraremos ejecutar pruebas en la infraestructura adecuada.
- Para el ensamblaje y la implementación usamos werf (en el sentido de componentes de infraestructura, esto también significa automáticamente que Helm está involucrado).
- No entraré en detalles para crear pruebas directamente: en nuestro caso, el cliente escribe las pruebas por sí mismo y solo nos aseguramos de que se ejecuten (y el informe correspondiente está disponible en la solicitud de fusión).
¿Cómo será la secuencia general de acciones?
- Ensamblaje de la aplicación: omitiremos la descripción de esta etapa.
- Implemente la aplicación en un espacio de nombres de clúster Kubernetes separado y ejecute las pruebas.
- Busque artefactos y analice un informe JUnit de GitLab.
- Eliminar el espacio de nombres creado anteriormente.
Ahora - a la implementación!
Personalización
Gitlab ci
Comencemos con el fragmento
.gitlab-ci.yaml
que describe la implementación de la aplicación y ejecuta las pruebas. La lista resultó ser bastante voluminosa, por lo tanto, se completa con comentarios:
variables:
Kubernetes
Ahora en el directorio
.helm/templates
, cree un YAML con Job -
tests-job.yaml
- para ejecutar las pruebas y los recursos de Kubernetes que necesita. Explicaciones ver después de la lista:
{{- if eq .Values.global.run_tests "yes" }} --- apiVersion: v1 kind: ConfigMap metadata: name: tests-script data: tests.sh: | echo "======================" echo "${APP_NAME} TESTS" echo "======================" cd /app npm run test:ci cp report.xml /app/test_results/${CI_COMMIT_REF_SLUG}/ echo "" echo "" echo "" chown -R 999:999 /app/test_results/${CI_COMMIT_REF_SLUG} --- apiVersion: batch/v1 kind: Job metadata: name: {{ .Chart.Name }}-test annotations: "helm.sh/hook": post-install,post-upgrade "helm.sh/hook-weight": "2" "werf/watch-logs": "true" spec: activeDeadlineSeconds: {{ .Values.global.ci_timeout }} backoffLimit: 1 template: metadata: name: {{ .Chart.Name }}-test spec: containers: - name: test command: ['bash', '-c', '/app/tests.sh'] {{ tuple "application" . | include "werf_container_image" | indent 8 }} env: - name: env value: {{ .Values.global.env }} - name: CI_COMMIT_REF_SLUG value: {{ .Values.global.commit_ref_slug }} - name: APP_NAME value: {{ .Chart.Name }} {{ tuple "application" . | include "werf_container_env" | indent 8 }} volumeMounts: - mountPath: /app/test_results/ name: data - mountPath: /app/tests.sh name: tests-script subPath: tests.sh tolerations: - key: dedicated operator: Exists - key: node-role.kubernetes.io/master operator: Exists restartPolicy: OnFailure volumes: - name: data persistentVolumeClaim: claimName: {{ .Chart.Name }}-pvc - name: tests-script configMap: name: tests-script --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: {{ .Chart.Name }}-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 10Mi storageClassName: {{ .Chart.Name }}-{{ .Values.global.commit_ref_slug }} volumeName: {{ .Values.global.commit_ref_slug }} --- apiVersion: v1 kind: PersistentVolume metadata: name: {{ .Values.global.commit_ref_slug }} spec: accessModes: - ReadWriteOnce capacity: storage: 10Mi local: path: /mnt/tests/ nodeAffinity: required: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - kube-master persistentVolumeReclaimPolicy: Delete storageClassName: {{ .Chart.Name }}-{{ .Values.global.commit_ref_slug }} {{- end }}
¿Qué recursos se describen en esta configuración? Al implementar, cree un espacio de nombres único para el proyecto (esto también se indica en
.gitlab-ci.yaml
-
tests-${CI_COMMIT_REF_SLUG}
) y enróllelo en él:
- ConfigMap con un script de prueba;
- Trabajo con una descripción de pod y la directiva de
command
especificada, que solo ejecuta las pruebas; - PV y PVC , que le permite almacenar datos de prueba.
Preste atención a la condición de introducción con
if
al comienzo del manifiesto; en consecuencia, otros archivos YAML del gráfico Helm con la aplicación deben envolverse en la construcción
inversa para que no se implementen durante la prueba. Eso es:
{{- if ne .Values.global.run_tests "yes" }} --- {{- end }}
Sin embargo, si las pruebas
requieren alguna infraestructura (por ejemplo, Redis, RabbitMQ, Mongo, PostgreSQL ...), sus YAML pueden desactivarse. Impleméntelos en un entorno de prueba ... por supuesto, retoque a su gusto.
Toque final
Porque el ensamblaje y la implementación usando werf hasta ahora
solo funciona en el servidor de compilación (con gitlab-runner), y el pod con pruebas se ejecuta en el asistente, deberá crear el directorio
/mnt/tests
en el asistente y dárselo al corredor,
por ejemplo, a través de NFS . Un ejemplo detallado con explicaciones se puede encontrar en la
documentación de K8s .
El resultado será:
user@kube-master:~$ cat /etc/exports | grep tests /mnt/tests IP_gitlab-builder/32(rw,nohide,insecure,no_subtree_check,sync,all_squash,anonuid=999,anongid=998) user@gitlab-runner:~$ cat /etc/fstab | grep tests IP_kube-master:/mnt/tests /mnt/tests nfs4 _netdev,auto 0 0
Nadie prohíbe hacer una bola NFS directamente en el gitlab-runner y luego montarla en vainas.
Nota
Puede preguntar, ¿por qué complicar todo con la creación de Job, si solo puede ejecutar el script de prueba directamente en el shell runner? La respuesta es bastante trivial ...
Algunas pruebas requieren acceso a la infraestructura (MongoDB, RabbitMQ, PostgreSQL, etc.) para verificar la exactitud de trabajar con ellas. Hacemos que las pruebas sean unificadas: con este enfoque, es fácil incluir tales entidades adicionales. Además de esto, obtenemos un enfoque
estándar en la implementación (incluso si se usa NFS, montaje de directorio adicional).
Resultado
¿Qué veremos cuando apliquemos la configuración preparada?
La solicitud de combinación mostrará estadísticas resumidas sobre las pruebas lanzadas en su última canalización:

Puede hacer clic en cada error aquí para obtener detalles:
NB : Un lector atento notará que estamos probando una aplicación NodeJS, y en las capturas de pantalla - .NET ... No se sorprenda: solo como parte de la preparación del artículo, no hubo errores al probar la primera aplicación, pero se encontraron en otra.Conclusión
Al parecer, nada complicado!
En principio, si ya tiene un constructor de shell y funciona, y no necesita Kubernetes, atornillar las pruebas será una tarea aún más simple que la descrita aquí. Y en la
documentación de GitLab CI encontrará ejemplos para Ruby, Go, Gradle, Maven y algunos otros.
PS
Lea también en nuestro blog: