اختبار نهاية إلى نهاية للخدمات المجهرية باستخدام الماسك

مساء الخير أرغب في تقديم أداة جديدة للاختبار الشامل للخدمات الميكروية - الماسك
الشعار


لماذا الاختبار؟


لماذا أحتاج إلى اختبار e2e؟ يوصي مارتن فاولر بتجنبه لصالح اختبارات أبسط.


ومع ذلك ، كلما كانت الاختبارات أعلى ، كلما كانت إعادة الكتابة أقل. يتم إعادة كتابة اختبارات الوحدة بالكامل تقريبًا. يجب أن تقضي الاختبارات الوظيفية أيضًا وقتك في حالة إعادة البناء الجاد. الاختبارات من البداية إلى النهاية يجب أن تختبر منطق العمل ، وتتغير في كثير من الأحيان.


بالإضافة إلى ذلك ، حتى التغطية الكاملة للاختبار لجميع الخدمات الميكروية لا تضمن تفاعلها الصحيح. يمكن للمطورين تطبيق البروتوكول بشكل غير صحيح (أخطاء في نوع الاسم / البيانات).


أو قم بتنفيذ وظائف جديدة تعتمد على نظام البيانات من الوثائق ، واحصل على مفاجأة في بيئة المنتج في شكل أخطاء عدم تطابق المخطط: فوضى في البيانات أو شخص ما نسي تحديث نظام البيانات.


وستكون اختبارات كل خدمة من الخدمات خضراء.


لماذا الاختبار التلقائي؟


حقا في مكان عملي السابق ، تقرر أن قضاء الوقت في نشر الاختبارات الآلية طويل للغاية وصعب ومكلف. النظام ليس كبيرًا (10-15 خدمة ميكروية مع كافكا مشترك). قرر CTO أن "الاختبارات ليست مهمة ، والشيء الرئيسي هو أن النظام يعمل." اختبارها يدويا على العديد من البيئات.


كيف بدا (العملية العامة):


  1. الاتفاق مع المطورين الآخرين (طرح جميع الخدمات الصغيرة المشاركة في الوظيفة الجديدة)
  2. طرح جميع الخدمات
  3. الاتصال بكفكا البعيد (مزدوج ssh في dmz)
  4. الاتصال بسجلات k8s
  5. شكّل رسالة kafka وأرسلها يدويًا (الحمد لله json)
  6. مشاهدة السجلات ، في محاولة لفهم ما إذا كان يعمل أم لا.

والآن يوجد القليل من القطران في برميل الشوكولاتة هذا: معظم الاختبارات يجب أن يقوم المستخدمون بإنشائها ، لأن إعادة استخدام الاختبارات الحالية أمر صعب.


أولاً ، نظرًا لتوزيع النظام ، كان للعديد من الخدمات قواعد بيانات خاصة بها تحتوي على معلومات حول المستخدمين.


ثانياً ، تم استخدام kafka لتخزين البيانات بشكل دائم. أي حتى إذا تم حذف / تغيير المعلومات في قاعدة البيانات ، فإن الخدمة ستظل تقرأها عند إعادة التشغيل.


كيف بدا تسجيل مستخدم اختبار جديد (تقريبًا):


  1. أدخل أي بيانات (الاسم ، البريد ، إلخ)
  2. إدخال البيانات الشخصية (العنوان ، الهاتف ، أي معلومات ضريبية)
  3. إدخال بيانات البنك (في الواقع ، بيانات البنك)
  4. أجب عن 20 إلى 40 سؤالًا (هل تشعر بالفعل بالألم؟)
  5. تعرف على هوية IDNow (شكرًا لك ، لقد أطفئتها في بيئة التطوير ، شكرًا لك ، على خشبة المسرح حوالي 5 دقائق أو أكثر ، لأن صندوق الحماية الخاص به يكون محملاً في بعض الأحيان)
  6. في هذه الخطوة ، يلزم فتح حساب في نظام جهة خارجية ولا يمكن القيام بأي شيء من خلال الواجهة الأمامية. تحتاج إلى الذهاب عن طريق ssh إلى kafka والعمل كخادم وهمية (إرسال رسالة مفادها أن الحساب مفتوح)
  7. بعد ذلك ، تحتاج إلى الانتقال إلى واجهة أخرى في الحساب الشخصي للمشرف وتأكيد المستخدم.

سوبر ، تم تسجيل المستخدم! الآن هناك ذبابة صغيرة في المرهم: تتطلب بعض الاختبارات أكثر من مستخدم اختبار واحد. وأحيانًا تفشل الاختبارات في المرة الأولى.


وكيف يتم التحقق من الوظائف الجديدة والتأكيد من فريق العمل؟
كل نفس يحتاج إلى تكرار على البيئة التالية.


وغني عن القول ، بعد فترة من الوقت بدأت تشعر وكأنها قرد ، الذي يفعل فقط ما يضغط ، تسجيل المستخدمين.


واجه بعض المطورين الآخرين (عادةً الواجهة الأمامية) مشاكل في الاتصال بـ kafka. ومع وجود خطأ في المحطة مع سلسلة من 80+ حرف (ليس الجميع يعلمون عن tmux).


الايجابيات :


  • لا حاجة لتكوين / كتابة أي شيء. اختبار مباشرة على بيئة التشغيل.
  • لا يتطلب مؤهلات عالية (يمكن للمتخصصين الأرخص القيام بذلك)

سلبيات :


  • يستغرق الكثير من الوقت (كلما زاد المسافة)
  • عادة يتم اختبار وظائف جديدة فقط (ليس من الواضح ما إذا كانت الوظيفة الحالية قد تم كسرها)
  • غالبًا ما يشارك المطورين المهرة في الاختبار اليدوي (يقوم المتخصصون المكلفون بعمل رخيص).

كيفية أتمتة؟


إذا قرأت هذا من خلال إيماءة رأسك والقول: "نعم ، إنها عملية رائعة ، والرجال يعرفون ماذا يفعلون" ، فلن تكون مهتمًا بذلك.


تأتي اختبارات e2e محلية الصنع بنوعين وتعتمد على أي من المبرمجين كان أكثر حرية:


  • الخلفية التي تعيش في بيئة الاختبار الخاصة بك. إنه يحمي منطق الاختبار ، الذي ينتقل عبر نقاط النهاية. يمكن أن يكون آليا جزئيا بسبب التفاعل مع CI.
  • برنامج نصي بنفس المنطق السلكي. الفرق الوحيد هو أنك تحتاج إلى الذهاب إلى مكان وتشغيله من هناك. إذا كنت تثق في CI ، فيمكنك تشغيلها تلقائيًا.

هذا يبدو جيدا. مشاكل؟


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


الايجابيات :


  • الأتمتة

سلبيات :


  • متطلبات إضافية لمؤهلات المطورين ممكنة (إذا كانت قيد التطوير في Java ، وكانت الاختبارات مكتوبة في Python)
  • كتابة التعليمات البرمجية لاختبار التعليمات البرمجية المكتوبة (من سيختبر الاختبارات؟)

هل هناك أي شيء جاهز؟


بالطبع ، مجرد إلقاء نظرة في اتجاه BDD . هناك خيار ، وهناك مقياس .


باختصار ، يصف المطور سيناريو العمل بلغة خاصة ، ثم ينفذ خطوات البرنامج النصي في الكود. عادة ما تكون اللغة قابلة للقراءة ، ويُفترض أنها ستتم قراءتها / كتابتها ليس فقط من قبل المطورين ، ولكن أيضًا بواسطة مديري المشاريع.


البرامج النصية جنبًا إلى جنب مع تنفيذ الخطوات موجودة أيضًا في مشروع منفصل وتديره منتجات الجهات الخارجية (Cucumber / Gauge / ...).


البرنامج النصي يشبه هذا:


Customer sign-up ================ * Go to sign up page Customer sign-up ---------------- tags: sign-up, customer * Sign up a new customer with name "John" email "jdoe@test.de" and "password" * Check if the sign up was successful 

والتنفيذ:


 @Step("Sign up as <customer> with email <test@example.com> and <password>") public void signUp(String customer, String email, String password) { WebDriver webDriver = Driver.webDriver; WebElement form = webDriver.findElement(By.id("new_user")); form.findElement(By.name("user[username]")).sendKeys(customer); form.findElement(By.name("user[email]")).sendKeys(email); form.findElement(By.name("user[password]")).sendKeys(password); form.findElement(By.name("user[password_confirmation]")).sendKeys(password); form.findElement(By.name("commit")).click(); } @Step("Check if the sign up was successful") public void checkSignUpSuccessful() { WebDriver webDriver = Driver.webDriver; WebElement message = webDriver.findElements(By.className("message")); assertThat(message.getText(), is("You have been signed up successfully!")); } 

مشروع كامل هنا


الايجابيات :


  • يتم وصف منطق الأعمال بلغة قابلة للقراءة البشرية وتخزينها في مكان واحد (يمكن استخدامه كوثائق)
  • يتم استخدام حلول جاهزة ، يحتاج المطورون فقط إلى معرفة كيفية استخدامها

سلبيات :


  • المديرين لن يقرأوا ويكتبوا النصوص
  • يجب عليك اتباع كل من المواصفات وتطبيقها (وهذا هو كتابة التعليمات البرمجية وتعديل المواصفات)

حسنا ، إذن لماذا الماسك؟


بالطبع ، لتبسيط العملية.


يكتب المطور البرامج النصية فقط في json / yaml ، ويقوم Catcher بتنفيذها. يتكون البرنامج النصي من خطوات منفذة بالتتابع ، على سبيل المثال:


 steps: - http: post: url: '127.0.0.1/save_data' body: {key: '1', data: 'foo'} - postgres: request: conf: 'dbname=test user=test host=localhost password=test' query: 'select * from test where id=1' 

يدعم Catcher قوالب jinja2 ، بحيث يمكنك استخدام المتغيرات بدلاً من القيم السلكية في المثال أعلاه. يمكن تخزين المتغيرات العامة في ملفات المخزون (كما في مجموعة) ، وسحبها من البيئة وتسجيلها جديدة:


 variables: bonus: 5000 initial_value: 1000 steps: - http: post: url: '{{ user_service }}/sign_up' body: {username: 'test_user_{{ RANDOM_INT }}', data: 'stub'} register: {user_id: '{{ OUTPUT.uuid }}' - kafka: consume: server: '{{ kafka }}' topic: '{{ new_users_topic }}' where: equals: {the: '{{ MESSAGE.uuid }}', is: '{{ user_id }}'} register: {balance: '{{ OUTPUT.initial_balance }}'} 

بالإضافة إلى ذلك ، يمكنك تشغيل خطوات الاختبار:


 - check: # check user's initial balance equals: {the: '{{ balance }}', is: '{{ initial_value + bonus }}'} 

يمكنك أيضًا تشغيل بعض البرامج النصية من البرامج النصية الأخرى ، والتي لها تأثير ممتاز على نظافة الكود وإعادة استخدامه (بما في ذلك بدء جزء فقط من الخطوات من خلال نظام العلامات ، والتأخير في التشغيل ، إلخ. الكعك).


 include: file: register_user.yaml as: sign_up steps: # .... some steps - run: include: sign_up # .... some steps 

يمكن أن يؤدي إدخال البرامج النصية واستخدامها إلى حل مشكلة انتظار مورد (انتظر خدمة أثناء بدء تشغيلها).


بالإضافة إلى الخطوات المدمجة الجاهزة ومستودع إضافي) ، من الممكن أن تكتب الوحدات النمطية الخاصة بك في بيثون (فقط وراثة من ExternalStep ) أو بأي لغة أخرى:


 #!/bin/bash one=$(echo ${1} | jq -r '.add.the') two=$(echo ${1} | jq -r '.add.to') echo $((${one} + ${two})) 

واستخدام:


 --- variables: one: 1 two: 2 steps: - math: add: {the: '{{ one }}', to: '{{ two }}'} register: {sum: '{{ OUTPUT }}'} 

يتم وضع البرامج النصية في ملف عامل ميناء وتشغيلها عبر CI.


كما يمكن استخدام هذه الصورة في Marathon / K8s لاختبار البيئة الحالية. في الوقت الحالي ، أعمل على خلفية (على غرار AnsibleTower) لجعل عملية الاختبار أسهل وأكثر راحة.


الايجابيات :


  • لا حاجة لكتابة كود (فقط في حالة الوحدات النمطية المخصصة)
  • تبديل البيئات من خلال ملفات المخزون (كما في المجموعة)
  • يمكنك استخدام الوحدات الخاصة بك (بأي لغة ، حتى sh)

سلبيات :


  • بناء جملة غير قابل للقراءة البشرية (مقارنة بأدوات BDD)

بدلا من الاستنتاج


عندما كتبت هذه الأداة ، أردت فقط تقليل الوقت الذي أقضيه عادة في الاختبارات. لقد حدث أن على كل شركة جديدة أن تكتب (أو تعيد كتابة) مثل هذا النظام.


ومع ذلك ، فقد تحولت الأداة إلى أنها أكثر مرونة مما توقعت. إذا كان شخص ما مهتمًا بالمقالة (أو الأداة نفسها) ، فيمكنني إخبارك بكيفية استخدام Catcher لتنظيم عمليات الترحيل المركزية وتحديث نظام الخدمة المجهرية.


محدث


كما أشرت في التعليقات ، لم يتم الكشف عن الموضوع.
سأحاول الإشارة هنا إلى الأطروحات الأكثر إثارة للجدل.


  • اختبارات نهاية إلى نهاية ليست اختبارات وحدة. أشرت بالفعل إلى م. فاولر في هذه المقالة. توجد اختبارات الوحدة في مشروع اختبار الواجهة الخلفية (دليل tests القياسية) ويتم تشغيلها في كل مرة يتغير فيها الرمز إلى CI. تعتبر اختبارات e2e مشروعًا منفصلاً ، وعادةً ما تستغرق وقتًا أطول ، وتختبر تفاعل جميع الخدمات المشاركة ولا تعرف شيئًا عن رمز مشروعك (الصندوق الأسود).
  • يجب ألا تستخدم اختبارات Catcher للتكامل (وأدناه). أنها مكلفة. من الأسرع بكثير كتابة اختبار على YP للواجهة الخلفية الحالية. لا تحتاج إلى اختبارات شاملة إلا إذا كان منطق عملك موزعًا على خدمتين أو أكثر.
  • الماسك هو أيضا BDD. من وجهة نظري ، الميزة الرئيسية على Gauge / Cucumber هي الوحدات الجاهزة الجاهزة وسهولة إضافتها. من الناحية المثالية ، فقط اختبار مكتوب. في الشركة الأخيرة ، كتبت جميع الاختبارات الأربعة على المكونات القياسية ، دون برمجة أي شيء. وفقًا لذلك ، ستكون متطلبات التأهيل (وسعر هذا المتخصص) أقل. هناك حاجة فقط لمعرفة json / yaml والقدرة على قراءة المواصفات.
  • لكتابة اختبارات Catcher ، يجب أن تتعلم Catcher-DSL. للأسف ، هذا صحيح. في البداية كنت أرغب في جعل الاختبارات تكتب نفسها ، مباشرة من الميكروفون. ولكن بعد ذلك ظننت أنهم سوف يطلقون النار لي كأمر غير ضروري ؛) كما ذكر أعلاه - يعد Catcher DSL هو المواصفات القياسية ل json / yaml والخطوة. لا شيء جديد في الأساس.
  • يمكنك استخدام التقنيات القياسية وكتابة شيء خاص بك. ومع ذلك ، نحن نتحدث عن الخدمات الصغيرة. هذا هو عدد كبير من التقنيات المختلفة والأسلحة النووية وعدد كبير من الفرق. وإذا كان الخيار jit command junit + testcontainers هو الخيار الواضح ، فسيختار فريق erlang شيئًا آخر. في شركة كبيرة تضم أكثر من 30 فريقًا في القمة ، سيقررون إرسال جميع الاختبارات إلى فريق البنية التحتية / qa الجديد. يمكنك أن تتخيل مدى سعادتهم في هذه الحديقة؟
  • إذا كان لديك 4-5 اختبارات e2e ، فيمكنك كتابة كل شيء بأي لغة نصية ونسيانها. ومع ذلك ، إذا تغير المنطق مع مرور الوقت ، فبعد عامين إلى أربعة أعوام ، سيتعين عليك إعادة تكوين رد الفعل ، وتوزيع منطق الأعمال للاختبارات مباشرةً وتنفيذ أساليب الوصول إلى المكونات التي تم اختبارها. حتى في النهاية تكتب الماسك الخاص بك ، وليس فقط مرنة للغاية. استغرق الأمر مني 4 تطبيقات لفهم هذا ؛)

Source: https://habr.com/ru/post/ar435452/


All Articles