على الرغم من حقيقة أن الجميع يعلمون أنه من الضروري والضروري اختبار البرنامج الخاص بك ، وأن الكثير منهم يقومون بذلك تلقائيًا لفترة طويلة ، لا توجد وصفة واحدة في الأماكن المفتوحة في Habr لإعداد مجموعة من هذه المنتجات الشائعة في هذه الفئة مثل GitLab و JUnit (المفضلة لدينا) . ملء هذه الفجوة!

استهلالي
أولاً ، سأوضح السياق:
- نظرًا لأن جميع تطبيقاتنا تعمل في Kubernetes ، فسننظر في إجراء الاختبارات في البنية التحتية المناسبة.
- للتجميع والنشر ، نستخدم werf (بمعنى مكونات البنية التحتية ، وهذا يعني أيضًا أن Helm متورط تلقائيًا).
- لن أخوض في تفاصيل إنشاء الاختبارات مباشرةً: في حالتنا ، يكتب العميل الاختبارات بنفسه ، ونضمن فقط تشغيلها (ويتوفر التقرير المقابل في طلب الدمج).
كيف سيبدو التسلسل الكلي للأعمال؟
- تجميع التطبيق - سنحذف وصف هذه المرحلة.
- نشر التطبيق إلى مساحة اسم كتلة Kubernetes منفصلة وإطلاق الاختبار.
- البحث عن القطع الأثرية وتحليل تقرير JUnit بواسطة GitLab.
- حذف مساحة الاسم التي تم إنشاؤها مسبقا.
الآن - إلى التنفيذ!
تعديل
Gitlab ci
لنبدأ
.gitlab-ci.yaml
يصف نشر التطبيق وتشغيل الاختبارات. لقد تبين أن القائمة ضخمة جدًا ، لذا فهي مستكملة تمامًا بالتعليقات:
variables:
Kubernetes
الآن ، في دليل
.helm/templates
، أنشئ YAML مع Job -
tests-job.yaml
- لتشغيل الاختبارات وموارد Kubernetes التي يحتاجها. تفسيرات انظر بعد الإدراج:
{{- 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 }}
ما هي الموارد الموصوفة في هذا التكوين؟ عند النشر ، قم بإنشاء مساحة اسم فريدة للمشروع (يشار إلى ذلك أيضًا في
.gitlab-ci.yaml
-
tests-${CI_COMMIT_REF_SLUG}
)
tests-${CI_COMMIT_REF_SLUG}
إلى ذلك:
- ConfigMap مع اختبار البرنامج النصي.
- العمل مع وصف جراب وتوجيه
command
المحدد ، الذي يعمل فقط الاختبارات ؛ - PV و PVC ، مما يسمح لك بتخزين بيانات الاختبار.
انتبه إلى شرط المقدمة
if
في بداية البيان - وفقًا لذلك ، يجب أن تكون ملفات YAML الأخرى من مخطط Helm مع التطبيق ملفوفة في البناء
العكسي حتى لا يتم نشرها أثناء الاختبار. هذا هو:
{{- if ne .Values.global.run_tests "yes" }} --- {{- end }}
ومع ذلك ، إذا كانت الاختبارات
تتطلب بعض البنية التحتية (على سبيل المثال ، Redis ، RabbitMQ ، Mongo ، PostgreSQL ...) - يمكن إيقاف تشغيل YAMLs الخاصة بهم. نشرها في بيئة اختبار ... بالطبع ، التغيير والتبديل كما تريد.
اللمسة النهائية
لأن التجميع والنشر باستخدام werf حتى الآن يعمل
فقط على خادم الإنشاء (مع برنامج gitlab-runner) ، وسيتم تشغيل pod مع الاختبارات على المعالج ، وستحتاج إلى إنشاء دليل
/mnt/tests
على المعالج ومنحه إلى runner ،
على سبيل المثال ، عبر NFS . يمكن العثور على مثال مفصل مع التفسيرات في
وثائق K8s .
ستكون النتيجة:
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
لا أحد يحظر صنع كرة NFS مباشرة على عداء gitlab ، ثم تركيبها في القرون.
تعليق
قد تسأل ، لماذا تعقد كل شيء مع إنشاء Job ، إذا كان يمكنك فقط تشغيل البرنامج النصي للاختبار مباشرةً على برنامج shell؟ الجواب تافهة جدا ...
تتطلب بعض الاختبارات الوصول إلى البنية التحتية (MongoDB ، RabbitMQ ، PostgreSQL ، إلخ) للتحقق من صحة العمل معهم. نجعل الاختبار موحدًا - مع هذا النهج ، يصبح من السهل تضمين مثل هذه الكيانات الإضافية. بالإضافة إلى ذلك ، نحصل على نهج
قياسي في النشر (حتى لو كان استخدام NFS ، دليل إضافي متصاعد).
يؤدي
ماذا سوف نرى عندما نطبق التكوين المعدة؟
سيُظهر طلب الدمج إحصائيات موجزة عن الاختبارات التي تم إطلاقها في خط الأنابيب الأخير:

يمكنك النقر على كل خطأ هنا للحصول على التفاصيل:
ملحوظة : سوف يلاحظ القارئ اليقظ أننا نقوم باختبار تطبيق NodeJS ، وفي لقطات الشاشة - .NET ... لا تفاجأ: فقط كجزء من إعداد المقال ، لم تكن هناك أخطاء في اختبار التطبيق الأول ، ولكن تم العثور عليها في تطبيق آخر.استنتاج
على ما يبدو ، لا شيء معقد!
من حيث المبدأ ، إذا كان لديك بالفعل أداة إنشاء صدفة وكانت تعمل ، ولم تكن بحاجة إلى Kubernetes ، فستكون مهمة اختبار اللولب مهمة أكثر بساطة من الموصوفة هنا. وفي
وثائق GitLab CI ، ستجد أمثلة على Ruby و Go و Gradle و Maven وبعض الآخرين.
PS
اقرأ أيضًا في مدونتنا: