متراصة لمئات إصدارات العملاء: كيف نكتب ونؤيد الاختبارات



مرحبا بالجميع!

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

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

عملية التنمية لدينا


لقد أوضحنا عملية التطوير لدينا:


لاعب الجولف هو مطور خلفية. في مرحلة ما ، تصل إليه مهمة التطوير ، وعادة ما تكون في شكل وثيقتين: المتطلبات من جانب العمل ووثيقة فنية تصف التغييرات في بروتوكول التفاعل بين الواجهة الخلفية والعملاء (تطبيقات الهاتف المحمول والموقع).

يكتب المطور الشفرة ويضعها موضع التنفيذ ، وقبل كل تطبيقات العميل. جميع الوظائف محمية من قبل بعض العلامات المميزة أو اختبارات A / B ، وهذا موصوف في مستند فني. بعد ذلك ، وفقًا للأولويات الحالية وخريطة طريق المنتج ، يتم إصدار تطبيقات العميل. بالنسبة لنا ، مطوري الواجهة الخلفية ، لا يمكن التنبؤ به تمامًا عندما يتم تنفيذ ميزة معينة على العملاء. دورة الإصدار لتطبيقات العملاء معقدة إلى حد ما وأطول من دورة عملنا ، وبالتالي فإن مديري المنتجات لدينا يمزجون أولوياتهم حرفيًا.

تتمتع ثقافة التطوير التي تتبناها الشركة بأهمية كبيرة: المطور الخلفي مسؤول عن الميزة من لحظة تنفيذها على الواجهة الخلفية إلى التكامل الأخير على النظام الأساسي الأخير الذي كان من المخطط أصلاً تنفيذه لهذه الميزة.

هذا الموقف ممكن: منذ ستة أشهر ، قمت بتطبيق بعض الميزات ، وفرق العملاء لم تنفذها لفترة طويلة ، لأن أولويات الشركة قد تغيرت ، وكنت مشغولة بالفعل بالعمل على مهام أخرى ، لديك مواعيد نهائية جديدة ، أولويات - وهنا يأتي زملائك يقولون: "هل تتذكر هذا الشيء الذي غسلته قبل ستة أشهر؟ إنها لا تعمل. " وبدلاً من الانخراط في مهام جديدة ، يمكنك إخماد الحرائق.



لذلك ، لدى مطورينا حافزًا غير معتاد لمبرمجي PHP - للتأكد من وجود عدد قليل من المشاكل أثناء مرحلة التكامل.

ماذا تريد أن تفعل أولاً وقبل كل شيء للتأكد من أن الميزة تعمل؟

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

وهنا الاختبارات الآلية تأتي لمساعدتنا.

اختبارات الوحدة


أبسط الاختبارات التي نكتبها هي اختبارات الوحدة. نستخدم لغة PHP كلغة رئيسية للواجهة الخلفية و PHPUnit كإطار لاختبار الوحدة. بالنظر إلى المستقبل ، أقول إن جميع اختبارات الواجهة الخلفية مكتوبة على أساس هذا الإطار.

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

Softmocks


الصعوبة الرئيسية التي تواجه المطورين عند كتابة اختبارات الوحدة هي رمز غير قابل للاختبار ، وهذا عادة ما يكون رمزًا قديمًا.

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

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

هذا هو ما يبدو للمطور:

//mock  \Badoo\SoftMocks::redefineConstant($constantName, $newValue); //mock  : , ,  \Badoo\SoftMocks::redefineMethod( $class, $method, $method_args, $fake_code ); //mock  \Badoo\SoftMocks::redefineFunction( $function, $function_args, $fake_code ); 

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

ومع ذلك ، واجهنا مشكلة: يبدو للمطورين أنه إذا كانت هناك SoftMocks ، فليست هناك حاجة لكتابة الكود الذي تم اختباره - يمكنك دائمًا "تمشيط" الكود مع mocks العالمية لدينا ، وسيعمل كل شيء بشكل جيد. ولكن هذا النهج يؤدي إلى رمز أكثر تعقيدًا وتراكم "العكازات". لذلك ، اعتمدنا عدة قواعد تسمح لنا بإبقاء الموقف تحت السيطرة:

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

تتم مراقبة الامتثال لهذه القواعد بعناية في مرحلة مراجعة التعليمات البرمجية.

اختبار طفرة


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

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

  • أخذ الرمز وتغطية الرمز ؛
  • parsim والبدء في تغيير التعليمات البرمجية: صواب إلى false ،> إلى> = ، + إلى - (بشكل عام ، ضرر بكل طريقة) ؛
  • لكل تغيير طفرة ، قم بتشغيل مجموعات الاختبار التي تغطي السلسلة التي تم تغييرها ؛
  • إذا سقطت الاختبارات ، فهي جيدة ولا تسمح لنا حقًا بكسر الشفرة ؛
  • إذا مرت الاختبارات ، على الأرجح ، فهي ليست فعالة بما يكفي ، على الرغم من التغطية ، وقد يكون من المفيد النظر إليها عن كثب ، لإعطاء بعض التأكيد (أو أن هناك منطقة لا يغطيها الاختبار).

هناك العديد من الأطر الجاهزة لـ PHP ، مثل Humbug و Infection. لسوء الحظ ، لم يناسبونا ، لأنهم لا يتوافقون مع SoftMocks. لذلك ، لقد كتبنا الأداة المساعدة لوحدة التحكم الخاصة بنا ، والتي تفعل الشيء نفسه ، لكننا نستخدم تنسيق تغطية الشفرة الداخلية الخاص بنا وأصدقاء لـ SoftMocks. الآن يبدأ المطور العمل يدويًا ويحلل الاختبارات التي كتبها ، لكننا نعمل على إدخال الأداة في عملية التطوير الخاصة بنا.

اختبار التكامل


بمساعدة اختبارات التكامل ، نتحقق من التفاعل مع مختلف الخدمات وقواعد البيانات.

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


يجب أن يظهر العرض الترويجي إذا:

  • المستخدم في الحقل "العمل" يشير إلى "مبرمج" ،
  • يشارك المستخدم في اختبار A / B HL18_promo ،
  • تم تسجيل المستخدم منذ أكثر من عامين.

بالضغط على زر "الحصول على تذكرة" ، يجب أن نحفظ بيانات هذا المستخدم في قائمة ما لنقلها إلى مديرينا الذين يقومون بتوزيع التذاكر.

حتى في هذا المثال البسيط ، هناك شيء لا يمكن التحقق منه باستخدام اختبارات الوحدة - التفاعل مع قاعدة البيانات. للقيام بذلك ، نحتاج إلى استخدام اختبارات التكامل.

النظر في الطريقة القياسية لاختبار التفاعل قاعدة البيانات التي تقدمها PHPUnit:

  1. رفع قاعدة بيانات الاختبار.
  2. نحن نستعد DataTables و DataSets.
  3. قم بإجراء الاختبار.
  4. نحن مسح قاعدة بيانات الاختبار.

ما الصعوبات التي تكمن في انتظار مثل هذا النهج؟

  • تحتاج إلى دعم هياكل DataTables و DataSets. إذا قمنا بتغيير تخطيط الجدول ، فمن الضروري عكس هذه التغييرات في الاختبار ، وهو أمر غير مناسب دائمًا ويتطلب وقتًا إضافيًا.
  • يستغرق وقتا طويلا لإعداد قاعدة البيانات. في كل مرة عند إعداد الاختبار ، نحتاج إلى تحميل شيء ما هناك ، وإنشاء بعض الجداول ، وهذا طويل ومزعج إذا كان هناك الكثير من الاختبارات.
  • وأهم عيب: إجراء هذه الاختبارات بالتوازي يجعلها غير مستقرة. بدأنا الاختبار A ، بدأ الكتابة إلى جدول الاختبار ، الذي أنشأه. في الوقت نفسه ، أطلقنا الاختبار B ، الذي يريد العمل مع جدول الاختبار نفسه. نتيجة لذلك ، تنشأ حالات انسداد متبادل وحالات أخرى غير متوقعة.

لتجنب هذه المشكلات ، قمنا بتطوير مكتبة صغيرة DBMocks الخاصة بنا.

DBMocks


مبدأ العملية على النحو التالي:

  1. بمساعدة SoftMocks ، نعترض كل الأغلفة التي نعمل من خلالها مع قواعد البيانات.
  2. متى
    يتحول الاستعلام إلى صور وهمية ، ويحلل استعلام SQL ويسحب DB + TableName منه ، ويحصل على المضيف من الاتصال.
  3. على نفس المضيف في tmpfs ، نقوم بإنشاء جدول مؤقت بنفس بنية الجدول الأصلي (نقوم بنسخ الهيكل باستخدام SHOW CREATE TABLE).
  4. بعد ذلك ، سنقوم بإعادة توجيه جميع الطلبات التي ستظهر من خلال هذا النموذج إلى جدول مؤقت تم إنشاؤه حديثًا.

ماذا يعطينا هذا:

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

اختبار API


يوضح GIF الفرق بين اختبارات الوحدة وواجهة برمجة التطبيقات:


القفل يعمل بشكل جيد ، لكنه متصل بالباب الخطأ.

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

اختبار تجمع المستخدم


ما الذي نحتاجه لكتابة هذه الاختبارات بنجاح؟ دعنا نعود إلى شروط عرض عرضنا الترويجي:

  • المستخدم في الحقل "العمل" يشير إلى "مبرمج" ،
  • يشارك المستخدم في اختبار A / B HL18_promo ،
  • تم تسجيل المستخدم منذ أكثر من عامين.

على ما يبدو ، هنا كل شيء عن المستخدم. وفي الواقع ، تتطلب 99٪ من اختبارات واجهة برمجة التطبيقات (API) وجود مستخدم مسجل معتمد ، وهو موجود في جميع الخدمات وقواعد البيانات.

أين يمكن الحصول عليها؟ يمكنك محاولة تسجيله في وقت الاختبار ، ولكن:

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


قمنا بتطوير أداة تسمى "مجموعة اختبار المستخدمين". يعتمد على فكرتين:

  1. نحن لا نسجل المستخدمين في كل مرة ، ولكن نستخدمها عدة مرات.
  2. بعد الاختبار ، نقوم بإعادة تعيين بيانات المستخدم إلى حالتها الأصلية (في وقت التسجيل). إذا لم يتم ذلك ، فستصبح الاختبارات غير مستقرة مع مرور الوقت ، لأنه سيتم "تلوث" المستخدمين بمعلومات من اختبارات أخرى.


يعمل شيء مثل هذا:



في مرحلة ما ، أردنا تشغيل اختبارات واجهة برمجة التطبيقات في بيئة الإنتاج. لماذا نريد هذا حتى؟ لأن البنية التحتية devel ليست هي نفسها الإنتاج.

على الرغم من أننا نحاول تكرار البنية الأساسية للإنتاج باستمرار بحجم أقل ، إلا أن تطوير لن يكون نسخة كاملة منه. للتأكد تمامًا من أن البنية الجديدة تلبي التوقعات ولا توجد أية مشكلات ، فإننا نقوم بتحميل الكود الجديد إلى مجموعة ما قبل الإنتاج ، والتي تعمل مع بيانات وخدمات الإنتاج ، ونجري اختبارات API الخاصة بنا هناك.

في هذه الحالة ، من المهم للغاية التفكير في كيفية عزل مستخدمي الاختبار عن المستخدمين الحقيقيين.

ماذا سيحدث إذا بدأ مستخدمو الاختبار في الظهور بشكل حقيقي في تطبيقنا.


كيفية عزل؟ كل من مستخدمينا لديه علامة is_test_user . في مرحلة التسجيل ، يصبح yes أو no ، ولم يعد يتغير. بواسطة هذه العلامة ، نعزل المستخدمين في جميع الخدمات. من المهم أيضًا استبعاد مستخدمي الاختبار من تحليلات الأعمال ونتائج اختبار A / B حتى لا يشوهوا الإحصاءات.

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

QA API


لا نحتاج فقط إلى مستخدم - بل نحتاج إليه مع بعض المعلمات: للعمل كمبرمج ، والمشاركة في اختبار A / B معين وتم تسجيله منذ أكثر من عامين. بالنسبة لمستخدمي الاختبار ، يمكننا بسهولة تعيين مهنة باستخدام واجهة برمجة تطبيقات الواجهة الخلفية الخاصة بنا ، ولكن الدخول في اختبارات A / B أمر محتمل. وحالة التسجيل منذ أكثر من عامين يصعب عمومًا الوفاء بها ، لأننا لا نعرف متى ظهر المستخدم في المجموعة.

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

لا يمكن تطبيق QA API إلا في حالة مستخدمي الاختبار: إذا لم يكن هناك علامة مقابلة ، فسوف يسقط الاختبار على الفور. إليك إحدى طرق QA API التي تتيح لك تغيير تاريخ تسجيل المستخدم إلى تاريخ تعسفي:



وستبدو ثلاث مكالمات من شأنها أن تسمح لك بتغيير بيانات مستخدم الاختبار بسرعة بحيث تلبي شروط عرض الترويجي:

  • في حقل "العمل" يشار إلى "مبرمج":
    addUserWorkEducation?user_id=ID&works[]=Badoo,

  • يشارك المستخدم في اختبار A / B HL18_promo:
    forceSplitTest?user_id=ID&test=HL18_promo
  • مسجل منذ أكثر من عامين:
    userCreatedChange?user_id=ID&created=2016-09-01


لأن هذا هو الباب الخلفي ، لا بد من التفكير في الأمن. لقد قمنا بحماية خدماتنا بعدة طرق:

  • معزولة على مستوى الشبكة: لا يمكن الوصول إلى الخدمات إلا من شبكة المكاتب ؛
  • مع كل طلب نمر سراً ، وبدون ذلك يستحيل الوصول إلى QA API حتى من شبكة المكاتب ؛
  • طرق العمل فقط مع مستخدمي الاختبار.


remotemocks


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

لدينا ثلاثة نصوص:



Badoo هو تطبيق متعدد اللغات ، لدينا مكون تعريب معقد يسمح لك بترجمة وتلقي الترجمات لموقع المستخدم الحالي بسرعة. يعمل المترجمون لدينا باستمرار على تحسين الترجمات وإجراء اختبارات A / B باستخدام الرموز ، والبحث عن صيغ أكثر نجاحًا. وأثناء إجراء الاختبار ، لا يمكننا معرفة النص الذي سيتم إرجاعه بواسطة الخادم - يمكن أن يتغير في أي وقت. ولكن يمكننا استخدام RemoteMocks للتحقق مما إذا كان قد تم الوصول إلى مكون الترجمة بشكل صحيح.

كيف يعمل RemoteMocks؟ يطلب الاختبار من الجهة الخلفية تهيئةها لجلستها ، وعند استلام جميع الطلبات اللاحقة ، يتحقق الجزء الخلفي من mocks للدورة الحالية. إذا كان الأمر كذلك ، فإنه ببساطة تهيئة لهم باستخدام SoftMocks.

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

 $this->remoteInterceptMethod( \Promo\HighLoadConference::class, 'saveUserEmailToDb', true ); 

حسنًا ، دعنا الآن نجمع اختبار واجهة برمجة التطبيقات:

 //       $app_startup = [ 'supported_promo_blocks' => [\Mobile\Proto\Enum\PromoBlockType::GENERIC_PROMO] ]; $Client = $this->getLoginedConnection(BmaFunctionalConfig::USER_TYPE_NEW, $app_startup); //  $Client->getQaApiClient()->addUserWorkEducation(['Badoo, ']); $Client->getQaApiClient()->forceSplitTest('HL18_promo'); $Client->getQaApiClient()->userCreatedChange('2016-09-01'); //     $this->remoteInterceptMethod(\Promo\HighLoadConference::class, 'saveUserEmail', true); //,   ,   $Resp = $Client->ServerGetPromoBlocks([]); $this->assertTrue($Resp->hasMessageType('CLIENT_NEXT_PROMO_BLOCKS')); $PromoBlock = $Resp->CLIENT_NEXT_PROMO_BLOCKS; … //   CTA, ,   ,   $Resp = $Client->ServerPromoAccepted($PromoBlock->getPromoId()); $this->assertTrue($Resp->hasMessageType('CLIENT_ACKNOWLEDGE_COMMAND')); 


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

قواعد استخدام اختبار API


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

لماذا هذا سيء؟ لأن اختبارات API بطيئة للغاية. يذهبون إلى الشبكة ، وينتقلون إلى الواجهة الخلفية ، التي تلتقط الجلسة ، وتذهب إلى قاعدة البيانات ومجموعة من الخدمات. لذلك ، قمنا بتطوير مجموعة من القواعد لاستخدام اختبارات API:
  • والغرض من اختبارات API هو التحقق من بروتوكول التفاعل بين العميل والخادم ، وكذلك التكامل الصحيح للرمز الجديد ؛

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

اختبارات واجهة المستخدم


نظرًا لأننا نفكر في هرم الأتمتة ، سأخبرك قليلاً عن اختبارات واجهة المستخدم.

لا يكتب مطورو Backend على Badoo اختبارات واجهة المستخدم - لهذا لدينا فريق متخصص في قسم ضمان الجودة. نحن نغطي الميزة باختبارات واجهة المستخدم عندما يتم طرحها بالفعل وتثبيتها ، لأننا نعتقد أنه من غير المعقول إنفاق الموارد على التشغيل التلقائي باهظ الثمن للميزة ، والتي ربما لن تتجاوز اختبار A / B.

نستخدم Calabash لاختبارات السيارات المتنقلة ، والسيلينيوم للويب. يتحدث عن منصتنا للأتمتة والاختبار.

اختبار المدى


لدينا الآن 100000 وحدة اختبار و 6000 اختبار دمج و 14000 اختبار API. إذا حاولت تشغيلها في مؤشر ترابط واحد ، فحتى على أقوى آلة لدينا ، سيستغرق التشغيل الكامل للجميع: وحدات - 40 دقيقة ، تكامل - 90 دقيقة ، اختبارات API - عشر ساعات. انها طويلة جدا.

الموازاة


تحدثنا عن تجربتنا في موازاة اختبارات وحدة في هذه المقالة .

الحل الأول ، الذي يبدو واضحًا ، هو إجراء الاختبارات في عدة مؤشرات ترابط. ولكن ذهبنا أبعد من ذلك وقدمنا ​​سحابة للإطلاق الموازي لتكون قادرة على توسيع نطاق موارد الأجهزة. المبسطة ، أعماله تبدو مثل هذا:



المهمة الأكثر إثارة للاهتمام هنا هي توزيع الاختبارات بين الخيوط ، أي تقسيمها إلى أجزاء.

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

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

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

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

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



نتيجة لذلك ، بدأت اختبارات الوحدة في العمل في دقيقة واحدة ، واختبارات التكامل في خمس دقائق ، واختبارات واجهة برمجة التطبيقات في 15 دقيقة. أي أن التشغيل الكامل بدلاً من 12 ساعة لا يستغرق أكثر من 22 دقيقة.

تشغيل اختبار تغطية الرمز


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

في مرحلة ما ، توصلنا إلى أنك لا تحتاج إلى تشغيل جميع الاختبارات في كل مرة - يمكنك إجراء عمليات تشغيل بناءً على تغطية الشفرة:

  1. خذ فرقنا فرع.
  2. نخلق قائمة من الملفات المعدلة.
  3. لكل ملف نحصل على قائمة الاختبارات ،
    التي تغطيها.
  4. من هذه الاختبارات نقوم بإنشاء مجموعة وتشغيلها في سحابة اختبار.

من أين تحصل على التغطية؟ نقوم بجمع البيانات مرة واحدة يوميًا عندما تكون البنية التحتية لبيئة التطوير في وضع الخمول. انخفض عدد الاختبارات التي يتم إجراؤها بشكل ملحوظ ، فقد زادت سرعة تلقي الملاحظات منها بشكل كبير. الربح!

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

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

API-, code coverage. , , . - , API- .

استنتاج


  • , . - , , - .
  • ≠ . code review , .
  • , , . .
  • . .
  • , ! , .


, Badoo PHP Meetup 16 . PHP-. , . ! 12:00, — YouTube- .

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


All Articles