ثلاث سنوات من الاختبارات الذاتية: كيفية زيادة السرعة وليس فقط


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


بادئ ذي بدء ، المصطلحات التي سيتم مناقشتها في المقال:


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

إيجابيات وسلبيات أنواع مختلفة من الاختبارات



اختبارات القبول


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

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


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

الاختبارات الوظيفية هي حل وسيط.


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

الكفاح من أجل السرعة


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


التجربة الأولى: موكي


Mock in PhpUnit هو كائن تم إنشاؤه ديناميكيًا والذي يتم توريث فئته ديناميكيًا من الفئة الساخرة. يمكنك تكوين ما ستعود به طرق mok ، ويمكنك التحقق من طرق moq وعدد المرات التي تم استدعاء المعلمات بها


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


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


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


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


أنا أعتبر تجربة mokas غير ناجحة من حيث تسريع الاختبارات.


التجربة الثانية: سكليتي


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


ولكن كان هناك سلبيات. لقد فقدنا الكثير من ميزات PostgreSQL الأصلية (json ، وبعض الوظائف التجميعية المفيدة ، والمزيد). كان لابد من كتابة الاستعلامات بحيث عملت على كل من PostgreSQL و SQLite.


التجربة الثالثة: تحسين بوستجرس


كان هذا القرار ناجحًا ، لكنه تسبب في بعض الألم. في مرحلة ما ، علمنا أنه يمكن تحسين PostgreSQL للاختبارات التلقائية ، مما يقلل من وقت الاستجابة بنحو أربع مرات. للقيام بذلك ، أضف بعض الإعدادات إلى postgresql.conf:


fsync=off synchronous_commit=off full_page_writes=off 

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


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


قليلا عن new


أود أيضًا أن أذكر خطر المشغل new . لا يمكن استبدال الخدمات التي تم إنشاؤها بمساعدتها بواسطة mokas و stubs. الاستنتاج:


  • لا تستخدم new لإنشاء الكائنات التي هي في الأساس خدمات.
  • يمكن استخدامه في المصانع ، لأنه يمكن استبدالها. ولكن المصانع نفسها لا ينبغي أن تنشأ من خلال new .
  • يمكن استخدامه لإنشاء نماذج ، كيانات ، DTO (كائن نقل البيانات) ، كائنات القيمة.

استنتاجات من ثلاث سنوات من الخبرة


  • في العمل السابق ، رفضنا اختبارات القبول ، لكن الآن سأجربها مرة أخرى: على الأرجح تم إصلاح العديد من الأخطاء في برامج تشغيل الويب.
  • إذا كنت بحاجة إلى تغطية وظائف جديدة مع الاختبارات ، تحتاج إلى كتابة الاختبارات الوظيفية فقط من وحدات التحكم / المكونات. في هذه الحالة ، لدينا خطر كبير من التغييرات الهيكلية ، اختبارات الوحدة غير مستقرة لهم.
  • لا ينبغي أن يكون هناك العديد من هذه الاختبارات ، لأن الكثير منها == ببطء ، لا تعمل بأسرع من الاختبارات المعيارية. يجدر تغطية الحالات التي يمكن أن "تطلق النار" فقط (لديهم احتمال حدوث خطأ في المستقبل).
  • تتم كتابة اختبارات الوحدة على طرق غنية بالخوارزمية (منطق معقد يحتاج إلى اختبار) أو على طرق تنطوي على مخاطر ضئيلة للتغيرات الهيكلية في المستقبل.
  • سلبيات موكا تتجاوز عموما الايجابيات. من المنطقي أن تستخدمها فقط كبديل للبوابات في واجهات برمجة التطبيقات الخارجية ، وأحيانًا خدمات من التعليمات البرمجية القديمة ، والتي يصعب اختبارها.
  • إذا قررت كتابة التعليمات البرمجية دون اختبار ، فمن المستحسن أن تفكر ، "عند إنشائها ، ماذا لو كنا في المستقبل لا نزال نرغب في كتابة اختبار له؟"
  • يجب أن تكون الاختبارات سهلة وممتعة في الكتابة ، فهي توفر الموثوقية والثقة وتساعد على فهم الكود بشكل أفضل وإدارة التبعيات.
  • إيلاء الاهتمام لسهولة الاختبارات. يجب على المرء أن يتصل برمز الاختبار بنفس طريقة الكود الذي يغطيه.
  • تركيبات DB - جزء من الاختبار ، يجب أن تكون قابلة للقراءة أيضًا

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


All Articles