اختبار الواجهة الأمامية

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

اختبار المبادئ


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

وهنا المبادئ الأربعة في السؤال.

number المبدأ رقم 1. يجب فهم الاختبارات على أنها مهام التحسين


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

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

No. المبدأ رقم 2. وينبغي تجنب الإفراط في استخدام mox.


تم تقديم أحد التفسيرات المفضلة لمصطلح "mok" في هذا العرض التقديمي من مؤتمر Assert.js 2018. افتتح المتحدث السؤال بعمق أكبر مما سأفتحه هنا. في الخطاب ، يتم مقارنة إنشاء الموكاس بـ "ثقب الثقوب في الواقع". وأعتقد أن هذه طريقة مرئية للغاية لإدراك الموكس. على الرغم من وجود موكاتس في اختباراتنا ، فإننا نقارن الانخفاض في "تكلفة" الاختبارات التي توفرها الموكاس بسبب تبسيط عملية الكتابة وتشغيل الاختبارات ، مع انخفاض في قيمة الاختبارات التي تتسبب في حدوث ثقب آخر في الواقع.

في السابق ، اعتمد المبرمجون لدينا اعتمادًا كبيرًا على اختبارات الوحدة المكتوبة بحيث تم استبدال جميع التبعيات التابعة للطفل باستخدام mokas باستخدام API لتقديم الإنزيمات الضحلة. تم فحص الكيانات المقدمة بهذه الطريقة باستخدام لقطات Jest . كُتبت كل هذه الاختبارات باستخدام نمط مماثل:

it('renders ', () => {   const wrapper = shallow();   //  ,              expect(wrapper).toMatchSnapshot(); }); 

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

No. المبدأ رقم 3. يجب أن تسهل الاختبارات إعادة بناء التعليمات البرمجية ، وليس تعقيدها.


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

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

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

No. المبدأ رقم 4. يجب أن تتولد الاختبارات عن كيفية عمل المستخدمين الحقيقيين مع التطبيق


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

أدوات الاختبار


الآن وقد حددنا الأهداف التي نريد تحقيقها ، فلنتحدث عن الأدوات التي اخترناها لهذا الغرض.

▍TypeScript


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

est فقط (اختبار وحدة)


كإطار لاختبار الكود ، نستخدم Jest و @ testing-library / react . في الاختبارات التي تم إنشاؤها باستخدام هذه الأدوات ، نقوم باختبار الوظائف أو المكونات بمعزل عن بقية النظام. نقوم عادةً باختبار الوظائف والمكونات التي يتم استخدامها غالبًا في أحد التطبيقات ، أو تلك التي لديها العديد من الطرق لتنفيذ التعليمات البرمجية. يصعب التحقق من هذه المسارات أثناء التكامل أو الاختبار الشامل (E2E).

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

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

أدوات الاختبار


yp السرو (اختبارات التكامل)


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

يحتوي استخدام mocks لمحاكاة طبقة الشبكة لتطبيق ما على العديد من نقاط القوة:

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

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

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

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

توضح هذه الاختبارات مبادئ الاختبار الخاصة بنا تمامًا. نسبة قيمتها إلى "السعر" يناسبنا. إعادة إنتاج الاختبارات بشكل مشابه جدًا تصرفات المستخدم الحقيقي التفاعل مع التطبيق. وفقط طبقة الشبكة من المشروع تم استبدال mokami.

yp السرو (اختبار من طرف إلى طرف)


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

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

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

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

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

سلبيات لدينا استراتيجية اختبار شامل


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

بادئ ذي بدء ، فإن تطبيق استراتيجية الاختبار هذه يعني أن جميع أعضاء الفريق يجب أن يكونوا على دراية بالعديد من أدوات الاختبار ، وليس فقط بأداة واحدة. يحتاج الجميع إلى معرفة Jest و @ test-library / react و Cypress. ولكن في الوقت نفسه ، لا يحتاج المطورون فقط إلى معرفة هذه الأدوات. كما يجب أن يكونوا قادرين على اتخاذ قرارات بشأن أي موقف يجب أن يستخدم. هل يستحق الأمر اختبار بعض الفرص الجديدة لكتابة اختبار شامل ، أم أن اختبار التكامل كافٍ؟ هل من الضروري ، بالإضافة إلى الاختبار الشامل أو التكامل ، كتابة اختبار وحدة للتحقق من التفاصيل الصغيرة لتنفيذ هذه الميزة الجديدة؟

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

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

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

النتائج


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

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

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

أعزائي القراء! ما هي الاستراتيجيات التي تتبعها في اختبار الواجهة الأمامية؟ ما هي أدوات اختبار الواجهة الأمامية التي تستخدمها؟


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


All Articles