لاختبار النظام ، عزل الآثار الجانبية

يعتبر أخذ الآثار الجانبية أحد أفضل الطرق لإنشاء رمز قابل للاختبار

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

Nock هي مكتبة شهيرة مكتوبة بلغة JavaScript مفيدة لرصد طلبات الشبكة. تقوم بإرجاع استجابة ثابتة للاختبارات بحيث يمكن تشغيلها حتى إذا لم يكن خادم HTTP متاحًا.

ومع ذلك ، إنها أيضًا رائحة.

الاقتران الناتج بين مصدر البيانات والنظام قيد الاختبار هو التكلفة التي يمكن أن تؤثر على إعادة هيكلة التعليمات البرمجية والصيانة.

إليكم السبب.

لنفترض أن هناك خادمًا يعرض قائمة منشورات ووظيفة تستهلك استجابة ذلك الخادم لإنشاء قائمة بعناوين المنشورات. يستخدم اختبار الوظيفة Nock لإيقاف الاستجابة من الخادم:

رسم تخطيطي يعرض كتلة على اليسار مع التعليق

رمز لديه تغطية لائقة. ومع ذلك ، هناك بعض المشاكل معها.

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

وينطبق الشيء نفسه إذا أجريت تغييرات على عنوان URL أو الرؤوس أو المعلمات التي يقوم Nock بتعنتها. يجب عليك تغيير الاختبارات حتى لو بقي سلوك النظام كما هو:

وظيفة "إنشاء قائمة المنشورات" هي "النظام قيد الاختبار" (SUT). البيانات من مكالمة HTTP هي مصدر البيانات.

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

رسم تخطيطي يُظهر كتلة على اليسار مع التسمية التوضيحية

بالنسبة لبيئة الاختبار ، يمكنك حقن "مصدر بيانات في الذاكرة". للإنتاج ، يمكنك استخدام "مصدر بيانات خادم HTTP".

"الواجهة العامة" في JSFiddle السابقة هي طريقة "البحث عن عنوان المشاركات". بغض النظر عن كيفية بناء الواجهة ، يمكنك التحكم في جميع المتصلين. لذلك ، التغييرات واضحة. يطلق مارتن فاولر على ذلك "واجهة غير منشورة".

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

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

مع التصميم الجديد ، قمت بفصل مصدر البيانات من النظام قيد الاختبار. لذلك ، يمكنك إزالة Nock.

يقلل التصميم الجديد أيضًا من العمل الضروري لإضافة قاعدة جديدة إلى النظام دون نسخ / لصق:

ومع ذلك ، يحتوي "مصدر بيانات خادم HTTP" على بعض المنطق الذي لم يتم اختباره داخل الوظيفة الخاصة "عنوان منشورات الاستعلام من html."

لاختبار ذلك ، يمكنك تكرار نفس النمط. ادفع الآثار الجانبية واجعل آلية "الحصول على طلب" قابلة للتوصيل في "مصدر بيانات خادم HTTP". وبهذه الطريقة لا يزال بإمكانك اختبار الرمز دون الحاجة إلى Nock:

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

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

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

Nock مفيد في إيقاف الاتصال في طبقة HTTP ولتقديم استجابة ثابتة. ومع ذلك ، استخدمها لماما. لكل اختبار تقوم به كعب ، يمكنك زيادة اقتران كبير وتكلفة التغيير.

إذا لم يتم استخدامها بشكل بسيط ، فيمكن لـ Nock إنشاء Nock Hell.

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

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

عزل الآثار الجانبية وتقييد استخدام أدوات مثل Nock على حدود التطبيق.

من المفترض أن يوفر لك ما يكفي من الثقة لإجراء تغييرات وليس كسر الأشياء.

انضم إلى المعركة ، وادفع الآثار الجانبية ، ثم ... اقذفها.

شكرا للقراءة. إذا كانت لديك بعض الملاحظات ، فتواصل معي على Twitter أو Facebook أو Github.

شكرًا لإدواردو سلومبو و Guilherme J. Tramontina على ملاحظاتهم الثاقبة لهذا المنشور.